]> gitweb.fperrin.net Git - GpsPrune.git/commitdiff
Version 10, May 2010
authoractivityworkshop <mail@activityworkshop.net>
Sat, 14 Feb 2015 14:35:04 +0000 (15:35 +0100)
committeractivityworkshop <mail@activityworkshop.net>
Sat, 14 Feb 2015 14:35:04 +0000 (15:35 +0100)
83 files changed:
tim/prune/App.java
tim/prune/FunctionLibrary.java
tim/prune/GpsPruner.java
tim/prune/I18nManager.java
tim/prune/config/Config.java
tim/prune/copyright.txt
tim/prune/data/Checker.java [new file with mode: 0644]
tim/prune/data/Coordinate.java
tim/prune/data/Track.java
tim/prune/data/TrackInfo.java
tim/prune/function/AboutScreen.java
tim/prune/function/AddMapSourceDialog.java [new file with mode: 0644]
tim/prune/function/DiskCacheConfig.java [new file with mode: 0644]
tim/prune/function/FullRangeDetails.java
tim/prune/function/MapSourceListModel.java [new file with mode: 0644]
tim/prune/function/PasteCoordinates.java
tim/prune/function/SetLanguage.java
tim/prune/function/SetMapBgFunction.java
tim/prune/function/SetPathsFunction.java
tim/prune/function/charts/Charter.java
tim/prune/function/srtm/LookupSrtmFunction.java [new file with mode: 0644]
tim/prune/function/srtm/SrtmTile.java [new file with mode: 0644]
tim/prune/function/srtm/TileFinder.java [new file with mode: 0644]
tim/prune/function/srtm/gen/GenerateTileLookup.java [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles1.txt [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles2.txt [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles3.txt [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles4.txt [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles5.txt [new file with mode: 0644]
tim/prune/function/srtm/gen/tiles6.txt [new file with mode: 0644]
tim/prune/function/srtm/srtmtiles.dat [new file with mode: 0644]
tim/prune/gui/DetailsDisplay.java
tim/prune/gui/DisplayUtils.java
tim/prune/gui/GenericChart.java [deleted file]
tim/prune/gui/MenuManager.java
tim/prune/gui/PhotoThumbnail.java
tim/prune/gui/ProfileChart.java [deleted file]
tim/prune/gui/map/CloudmadeMapSource.java [new file with mode: 0644]
tim/prune/gui/map/DiskTileCacher.java [new file with mode: 0644]
tim/prune/gui/map/MapCanvas.java
tim/prune/gui/map/MapSource.java [new file with mode: 0644]
tim/prune/gui/map/MapSourceLibrary.java [new file with mode: 0644]
tim/prune/gui/map/MapTileCacher.java [deleted file]
tim/prune/gui/map/MapTileConfig.java [deleted file]
tim/prune/gui/map/MapTileManager.java [new file with mode: 0644]
tim/prune/gui/map/MemTileCacher.java [new file with mode: 0644]
tim/prune/gui/map/MffMapSource.java [new file with mode: 0644]
tim/prune/gui/map/OsmMapSource.java [new file with mode: 0644]
tim/prune/gui/profile/AltitudeData.java [new file with mode: 0644]
tim/prune/gui/profile/ProfileChart.java [new file with mode: 0644]
tim/prune/gui/profile/ProfileData.java [new file with mode: 0644]
tim/prune/gui/profile/SpeedData.java [new file with mode: 0644]
tim/prune/jpeg/ExifGateway.java [new file with mode: 0644]
tim/prune/jpeg/ExifLibrary.java [new file with mode: 0644]
tim/prune/jpeg/ExternalExifLibrary.java [new file with mode: 0644]
tim/prune/jpeg/InternalExifLibrary.java [new file with mode: 0644]
tim/prune/jpeg/JpegData.java [moved from tim/prune/drew/jpeg/JpegData.java with 70% similarity]
tim/prune/jpeg/drew/ExifReader.java [moved from tim/prune/drew/jpeg/ExifReader.java with 92% similarity]
tim/prune/jpeg/drew/JpegException.java [moved from tim/prune/drew/jpeg/JpegException.java with 93% similarity]
tim/prune/jpeg/drew/JpegSegmentData.java [moved from tim/prune/drew/jpeg/JpegSegmentData.java with 95% similarity]
tim/prune/jpeg/drew/JpegSegmentReader.java [moved from tim/prune/drew/jpeg/JpegSegmentReader.java with 96% similarity]
tim/prune/jpeg/drew/Rational.java [moved from tim/prune/drew/jpeg/Rational.java with 94% similarity]
tim/prune/lang/prune-texts_af.properties
tim/prune/lang/prune-texts_de.properties
tim/prune/lang/prune-texts_de_CH.properties
tim/prune/lang/prune-texts_en.properties
tim/prune/lang/prune-texts_es.properties
tim/prune/lang/prune-texts_fr.properties
tim/prune/lang/prune-texts_in.properties
tim/prune/lang/prune-texts_it.properties
tim/prune/lang/prune-texts_ja.properties
tim/prune/lang/prune-texts_pl.properties
tim/prune/lang/prune-texts_pt.properties
tim/prune/lang/prune-texts_ro.properties
tim/prune/lang/prune-texts_tr.properties
tim/prune/lang/prune-texts_zh.properties
tim/prune/load/JpegLoader.java
tim/prune/load/NmeaFileLoader.java
tim/prune/load/NmeaMessage.java
tim/prune/load/xml/ZipFileLoader.java
tim/prune/readme.txt
tim/prune/save/GpxCacher.java
tim/prune/undo/UndoLookupSrtm.java [new file with mode: 0644]

index ab9724b3bb90bd99de28f882a0ef4337bac39e42..07f68b1222e5dbc4b2214e94dfacc91405c8f896 100644 (file)
@@ -10,6 +10,7 @@ import javax.swing.JFrame;
 import javax.swing.JOptionPane;
 
 import tim.prune.data.Altitude;
 import javax.swing.JOptionPane;
 
 import tim.prune.data.Altitude;
+import tim.prune.data.Checker;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Field;
 import tim.prune.data.LatLonRectangle;
 import tim.prune.data.DataPoint;
 import tim.prune.data.Field;
 import tim.prune.data.LatLonRectangle;
@@ -578,14 +579,13 @@ public class App
        {
                // create undo object
                UndoCreatePoint undo = new UndoCreatePoint();
        {
                // create undo object
                UndoCreatePoint undo = new UndoCreatePoint();
+               _undoStack.add(undo);
                // add point to track
                inPoint.setSegmentStart(true);
                _track.appendPoints(new DataPoint[] {inPoint});
                // ensure track's field list contains point's fields
                _track.extendFieldList(inPoint.getFieldList());
                _trackInfo.selectPoint(_trackInfo.getTrack().getNumPoints()-1);
                // add point to track
                inPoint.setSegmentStart(true);
                _track.appendPoints(new DataPoint[] {inPoint});
                // ensure track's field list contains point's fields
                _track.extendFieldList(inPoint.getFieldList());
                _trackInfo.selectPoint(_trackInfo.getTrack().getNumPoints()-1);
-               // add undo object to stack
-               _undoStack.add(undo);
                // update listeners
                UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.createpoint"));
        }
                // update listeners
                UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.createpoint"));
        }
@@ -647,8 +647,8 @@ public class App
         * @param inAltFormat altitude format
         * @param inSourceInfo information about the source of the data
         */
         * @param inAltFormat altitude format
         * @param inSourceInfo information about the source of the data
         */
-       public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray, Altitude.Format inAltFormat,
-               SourceInfo inSourceInfo)
+       public void informDataLoaded(Field[] inFieldArray, Object[][] inDataArray,
+               Altitude.Format inAltFormat, SourceInfo inSourceInfo)
        {
                // Check whether loaded array can be properly parsed into a Track
                Track loadedTrack = new Track();
        {
                // Check whether loaded array can be properly parsed into a Track
                Track loadedTrack = new Track();
@@ -660,6 +660,11 @@ public class App
                        loadNextFile();
                        return;
                }
                        loadNextFile();
                        return;
                }
+               // Check for doubled track
+               if (Checker.isDoubledTrack(loadedTrack)) {
+                       JOptionPane.showMessageDialog(_frame, I18nManager.getText("dialog.open.contentsdoubled"),
+                               I18nManager.getText("function.open"), JOptionPane.WARNING_MESSAGE);
+               }
                // Decide whether to load or append
                if (_track.getNumPoints() > 0)
                {
                // Decide whether to load or append
                if (_track.getNumPoints() > 0)
                {
@@ -716,7 +721,8 @@ public class App
                }
                UpdateMessageBroker.informSubscribers();
                // Update status bar
                }
                UpdateMessageBroker.informSubscribers();
                // Update status bar
-               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile") + " '" + inSourceInfo.getName() + "'");
+               UpdateMessageBroker.informSubscribers(I18nManager.getText("confirm.loadfile")
+                       + " '" + inSourceInfo.getName() + "'");
                // update menu
                _menuManager.informFileLoaded();
                // load next file if there's a queue
                // update menu
                _menuManager.informFileLoaded();
                // load next file if there's a queue
index 0e642dd37a0348e9e91254ce54265eca6a616616..1f7bcfd2d8562091816c4984cfd01ae3b712584f 100644 (file)
@@ -7,6 +7,7 @@ import tim.prune.function.compress.CompressTrackFunction;
 import tim.prune.function.distance.DistanceFunction;
 import tim.prune.function.edit.PointNameEditor;
 import tim.prune.function.gpsies.GetGpsiesFunction;
 import tim.prune.function.distance.DistanceFunction;
 import tim.prune.function.edit.PointNameEditor;
 import tim.prune.function.gpsies.GetGpsiesFunction;
+import tim.prune.function.srtm.LookupSrtmFunction;
 import tim.prune.load.GpsLoader;
 import tim.prune.save.GpsSaver;
 import tim.prune.save.GpxExporter;
 import tim.prune.load.GpsLoader;
 import tim.prune.save.GpsSaver;
 import tim.prune.save.GpxExporter;
@@ -28,6 +29,7 @@ public abstract class FunctionLibrary
        public static RearrangeWaypointsFunction FUNCTION_REARRANGE_WAYPOINTS = null;
        public static GenericFunction FUNCTION_REARRANGE_PHOTOS = null;
        public static GenericFunction FUNCTION_COMPRESS = null;
        public static RearrangeWaypointsFunction FUNCTION_REARRANGE_WAYPOINTS = null;
        public static GenericFunction FUNCTION_REARRANGE_PHOTOS = null;
        public static GenericFunction FUNCTION_COMPRESS = null;
+       public static GenericFunction FUNCTION_LOOKUP_SRTM = null;
        public static GenericFunction FUNCTION_ADD_TIME_OFFSET  = null;
        public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET  = null;
        public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES  = null;
        public static GenericFunction FUNCTION_ADD_TIME_OFFSET  = null;
        public static GenericFunction FUNCTION_ADD_ALTITUDE_OFFSET  = null;
        public static GenericFunction FUNCTION_CONVERT_NAMES_TO_TIMES  = null;
@@ -44,6 +46,7 @@ public abstract class FunctionLibrary
        public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
        public static GenericFunction FUNCTION_GET_GPSIES = null;
        public static GenericFunction FUNCTION_SET_MAP_BG = null;
        public static GenericFunction FUNCTION_FULL_RANGE_DETAILS = null;
        public static GenericFunction FUNCTION_GET_GPSIES = null;
        public static GenericFunction FUNCTION_SET_MAP_BG = null;
+       public static GenericFunction FUNCTION_SET_DISK_CACHE = null;
        public static GenericFunction FUNCTION_SET_PATHS  = null;
        public static GenericFunction FUNCTION_SET_KMZ_IMAGE_SIZE = null;
        public static GenericFunction FUNCTION_SET_COLOURS = null;
        public static GenericFunction FUNCTION_SET_PATHS  = null;
        public static GenericFunction FUNCTION_SET_KMZ_IMAGE_SIZE = null;
        public static GenericFunction FUNCTION_SET_COLOURS = null;
@@ -70,6 +73,7 @@ public abstract class FunctionLibrary
                FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
                FUNCTION_REARRANGE_PHOTOS = new RearrangePhotosFunction(inApp);
                FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
                FUNCTION_REARRANGE_WAYPOINTS = new RearrangeWaypointsFunction(inApp);
                FUNCTION_REARRANGE_PHOTOS = new RearrangePhotosFunction(inApp);
                FUNCTION_COMPRESS = new CompressTrackFunction(inApp);
+               FUNCTION_LOOKUP_SRTM = new LookupSrtmFunction(inApp);
                FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
                FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
                FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
                FUNCTION_ADD_TIME_OFFSET = new AddTimeOffset(inApp);
                FUNCTION_ADD_ALTITUDE_OFFSET = new AddAltitudeOffset(inApp);
                FUNCTION_CONVERT_NAMES_TO_TIMES = new ConvertNamesToTimes(inApp);
@@ -86,6 +90,7 @@ public abstract class FunctionLibrary
                FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
                FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
                FUNCTION_SET_MAP_BG = new SetMapBgFunction(inApp);
                FUNCTION_FULL_RANGE_DETAILS = new FullRangeDetails(inApp);
                FUNCTION_GET_GPSIES = new GetGpsiesFunction(inApp);
                FUNCTION_SET_MAP_BG = new SetMapBgFunction(inApp);
+               FUNCTION_SET_DISK_CACHE = new DiskCacheConfig(inApp);
                FUNCTION_SET_PATHS = new SetPathsFunction(inApp);
                FUNCTION_SET_KMZ_IMAGE_SIZE = new SetKmzImageSize(inApp);
                FUNCTION_SET_COLOURS = new SetColours(inApp);
                FUNCTION_SET_PATHS = new SetPathsFunction(inApp);
                FUNCTION_SET_KMZ_IMAGE_SIZE = new SetKmzImageSize(inApp);
                FUNCTION_SET_COLOURS = new SetColours(inApp);
index 7a172a4a64ceeb0a2576de987a4240b3018cc423..ac61501a2cadc025315918261f138fcc91f367ef 100644 (file)
@@ -17,11 +17,11 @@ import tim.prune.config.ConfigException;
 import tim.prune.gui.DetailsDisplay;
 import tim.prune.gui.IconManager;
 import tim.prune.gui.MenuManager;
 import tim.prune.gui.DetailsDisplay;
 import tim.prune.gui.IconManager;
 import tim.prune.gui.MenuManager;
-import tim.prune.gui.ProfileChart;
 import tim.prune.gui.SelectorDisplay;
 import tim.prune.gui.StatusBar;
 import tim.prune.gui.Viewport;
 import tim.prune.gui.map.MapCanvas;
 import tim.prune.gui.SelectorDisplay;
 import tim.prune.gui.StatusBar;
 import tim.prune.gui.Viewport;
 import tim.prune.gui.map.MapCanvas;
+import tim.prune.gui.profile.ProfileChart;
 
 /**
  * Prune is a tool to visualize, edit, convert and prune GPS data
 
 /**
  * Prune is a tool to visualize, edit, convert and prune GPS data
@@ -33,12 +33,15 @@ import tim.prune.gui.map.MapCanvas;
 public class GpsPruner
 {
        /** Version number of application, used in about screen and for version check */
 public class GpsPruner
 {
        /** Version number of application, used in about screen and for version check */
-       public static final String VERSION_NUMBER = "9";
+       public static final String VERSION_NUMBER = "10";
        /** Build number, just used for about screen */
        /** Build number, just used for about screen */
-       public static final String BUILD_NUMBER = "176";
+       public static final String BUILD_NUMBER = "189";
        /** Static reference to App object */
        private static App APP = null;
 
        /** Static reference to App object */
        private static App APP = null;
 
+       /** Program name, used for Frame title and for Macs also on the system bar */
+       private static final String PROGRAM_NAME = "Prune";
+
 
        /**
         * Main method
 
        /**
         * Main method
@@ -52,6 +55,13 @@ public class GpsPruner
                String configFilename = null;
                ArrayList<File> dataFiles = new ArrayList<File>();
                boolean showUsage = false;
                String configFilename = null;
                ArrayList<File> dataFiles = new ArrayList<File>();
                boolean showUsage = false;
+
+               // Mac OSX - specific properties (Mac insists that this is done as soon as possible)
+               if (System.getProperty("mrj.version") != null) {
+                       System.setProperty("apple.laf.useScreenMenuBar", "true"); // menu at top of screen
+                       System.setProperty("com.apple.mrj.application.apple.menu.about.name", PROGRAM_NAME);
+               }
+               // Loop over given arguments, if any
                for (int i=0; i<args.length; i++)
                {
                        String arg = args[i];
                for (int i=0; i<args.length; i++)
                {
                        String arg = args[i];
@@ -168,7 +178,8 @@ public class GpsPruner
         */
        private static void launch(ArrayList<File> inDataFiles)
        {
         */
        private static void launch(ArrayList<File> inDataFiles)
        {
-               JFrame frame = new JFrame("Prune");
+               // Initialise Frame
+               JFrame frame = new JFrame(PROGRAM_NAME);
                APP = new App(frame);
 
                // make menu
                APP = new App(frame);
 
                // make menu
index 143d7c884b418584d9ffba8a242dffb95e404b0e..349db3fcaff83bace412ebdf02e459b28d1e9199 100644 (file)
@@ -87,18 +87,18 @@ public abstract class I18nManager
        public static String getText(String inKey)
        {
                // look in external props file if available
        public static String getText(String inKey)
        {
                // look in external props file if available
-               if (ExternalPropsFile != null && ExternalPropsFile.containsKey(inKey))
+               if (ExternalPropsFile != null)
                {
                {
-                       return ExternalPropsFile.getProperty(inKey);
+                       String extText = ExternalPropsFile.getProperty(inKey);
+                       if (extText != null) return extText;
                }
                // look in extra texts if available
                if (LocalTexts != null)
                {
                        try
                        {
                }
                // look in extra texts if available
                if (LocalTexts != null)
                {
                        try
                        {
-                               if (LocalTexts.containsKey(inKey)) {
-                                       return LocalTexts.getString(inKey);
-                               }
+                               String localText = LocalTexts.getString(inKey);
+                               if (localText != null) return localText;
                        }
                        catch (MissingResourceException mre) {}
                }
                        }
                        catch (MissingResourceException mre) {}
                }
@@ -107,9 +107,8 @@ public abstract class I18nManager
                {
                        try
                        {
                {
                        try
                        {
-                               if (EnglishTexts.containsKey(inKey)) {
-                                       return EnglishTexts.getString(inKey);
-                               }
+                               String engText = EnglishTexts.getString(inKey);
+                               if (engText != null) return engText;
                        }
                        catch (MissingResourceException mre) {}
                }
                        }
                        catch (MissingResourceException mre) {}
                }
index a822b6e34ebef38da13b798f6afa7460c288f0eb..14231383fc03d860b4eea332575837e6cede4a0d 100644 (file)
@@ -37,12 +37,16 @@ public abstract class Config
        public static final String KEY_POVRAY_FONT = "prune.povrayfont";
        /** Key for metric/imperial */
        public static final String KEY_METRIC_UNITS = "prune.metricunits";
        public static final String KEY_POVRAY_FONT = "prune.povrayfont";
        /** Key for metric/imperial */
        public static final String KEY_METRIC_UNITS = "prune.metricunits";
-       /** Key for map server index */
-       public static final String KEY_MAPSERVERINDEX = "prune.mapserverindex";
-       /** Key for map server url */
-       public static final String KEY_MAPSERVERURL = "prune.mapserverurl";
+       /** Key for index of map source */
+       public static final String KEY_MAPSOURCE_INDEX = "prune.mapsource";
+       /** Key for String containing custom map sources */
+       public static final String KEY_MAPSOURCE_LIST = "prune.mapsourcelist";
        /** Key for show map flag */
        public static final String KEY_SHOW_MAP = "prune.showmap";
        /** Key for show map flag */
        public static final String KEY_SHOW_MAP = "prune.showmap";
+       /** Key for path to disk cache */
+       public static final String KEY_DISK_CACHE = "prune.diskcache";
+       /** Key for working online flag */
+       public static final String KEY_ONLINE_MODE = "prune.onlinemode";
        /** Key for width of thumbnails in kmz */
        public static final String KEY_KMZ_IMAGE_WIDTH = "prune.kmzimagewidth";
        /** Key for height of thumbnails in kmz */
        /** Key for width of thumbnails in kmz */
        public static final String KEY_KMZ_IMAGE_WIDTH = "prune.kmzimagewidth";
        /** Key for height of thumbnails in kmz */
@@ -217,7 +221,7 @@ public abstract class Config
        /**
         * Get the given configuration setting as a boolean
         * @param inKey key
        /**
         * Get the given configuration setting as a boolean
         * @param inKey key
-        * @return configuration setting as a boolean
+        * @return configuration setting as a boolean (default to true)
         */
        public static boolean getConfigBoolean(String inKey)
        {
         */
        public static boolean getConfigBoolean(String inKey)
        {
index 7839745c74830dfeb92e4af7c369fe35d3eab1d1..a24ac608ab7c99cb329f8a6ad0a2ad3f57065fea 100644 (file)
@@ -1,8 +1,9 @@
 The source code of Prune is copyright 2006-2010 activityworkshop.net
 and distributed under the terms of the Gnu GPL version 2.
 
 The source code of Prune is copyright 2006-2010 activityworkshop.net
 and distributed under the terms of the Gnu GPL version 2.
 
-The package drew.jpeg is taken from Drew Noakes' "Metadata extractor"
-which is copyright Drew Noakes 2002-2006 and was placed in the public domain.
+Portions of the package jpeg.drew (if included in this package) were taken
+from Drew Noakes' "Metadata extractor" v2.3.1 which is
+copyright Drew Noakes 2002-2006 and was placed in the public domain.
 
 Translations are copyright various contributors, some of whom are named
 in the source code and some preferred to remain anonymous.
\ No newline at end of file
 
 Translations are copyright various contributors, some of whom are named
 in the source code and some preferred to remain anonymous.
\ No newline at end of file
diff --git a/tim/prune/data/Checker.java b/tim/prune/data/Checker.java
new file mode 100644 (file)
index 0000000..274c3e7
--- /dev/null
@@ -0,0 +1,68 @@
+package tim.prune.data;
+
+/**
+ * Class to provide checking functions
+ */
+public abstract class Checker
+{
+
+       /**
+        * Check if a given track is doubled, so that each point is given twice,
+        * once as waypoint and again as track point
+        * @param inTrack track to check
+        * @return true if track is doubled, false otherwise
+        */
+       public static boolean isDoubledTrack(Track inTrack)
+       {
+               // Check for empty track
+               if (inTrack == null || inTrack.getNumPoints() < 2) {return false;}
+               // Check for non-even number of points
+               final int numPoints = inTrack.getNumPoints();
+               if (numPoints % 2 == 1) {return false;}
+               // Loop through first half of track
+               final int halfNum = numPoints / 2;
+               for (int i=0; i<halfNum; i++)
+               {
+                       DataPoint firstPoint = inTrack.getPoint(i);
+                       DataPoint secondPoint = inTrack.getPoint(i + halfNum);
+                       if (!firstPoint.getLatitude().equals(secondPoint.getLatitude())
+                               || !firstPoint.getLongitude().equals(secondPoint.getLongitude())) {
+                               return false;
+                       }
+               }
+               // Passed the test, so contents must all be doubled
+               return true;
+       }
+
+       /**
+        * Find the index of the next segment start after the given index
+        * @param inTrack track object
+        * @param inIndex current index
+        * @return index of next segment start
+        */
+       public static int getNextSegmentStart(Track inTrack, int inIndex)
+       {
+               int i = inIndex + 1;
+               DataPoint point = null;
+               while ((point=inTrack.getPoint(i)) != null && !point.getSegmentStart()) {
+                       i++;
+               }
+               return Math.min(i, inTrack.getNumPoints()-1);
+       }
+
+       /**
+        * Find the index of the previous segment start before the given index
+        * @param inTrack track object
+        * @param inIndex current index
+        * @return index of previous segment start
+        */
+       public static int getPreviousSegmentStart(Track inTrack, int inIndex)
+       {
+               int i = inIndex - 1;
+               DataPoint point = null;
+               while ((point=inTrack.getPoint(i)) != null && !point.getSegmentStart()) {
+                       i--;
+               }
+               return Math.max(i, 0);
+       }
+}
index 190c66573b13e2c251a434407bc02315d34c0984..44ab779ab6c1a0d66f1254c3df6fb82391a955fb 100644 (file)
@@ -117,6 +117,7 @@ public abstract class Coordinate
                        }
                        // parse fields according to number found
                        _degrees = (int) fields[0];
                        }
                        // parse fields according to number found
                        _degrees = (int) fields[0];
+                       _asDouble = _degrees;
                        _originalFormat = hasCardinal?FORMAT_DEG:FORMAT_DEG_WITHOUT_CARDINAL;
                        _fracDenom = 10;
                        if (numFields == 2)
                        _originalFormat = hasCardinal?FORMAT_DEG:FORMAT_DEG_WITHOUT_CARDINAL;
                        _fracDenom = 10;
                        if (numFields == 2)
index d33886ea3f22eb2eee5057cba3bbd6a2cd9a8524..83ac9547f3ede67149ee5a1d0cce85758d45adae 100644 (file)
@@ -748,11 +748,14 @@ public class Track
        }
 
        /**
        }
 
        /**
-        * @return true if track has altitude data (which are not all zero)
+        * @return true if track has altitude data
         */
        public boolean hasAltitudeData()
        {
         */
        public boolean hasAltitudeData()
        {
-               return getAltitudeRange().getMaximum() > 0;
+               for (int i=0; i<_numPoints; i++) {
+                       if (_dataPoints[i].hasAltitude()) {return true;}
+               }
+               return false;
        }
 
        /**
        }
 
        /**
index 254de9341e6119d098ef327196cefdfa0b20a7fa..6fa8e90b2e54ba39186053fcc38a1433d5ec298c 100644 (file)
@@ -399,7 +399,9 @@ public class TrackInfo
        {
                // See whether to start selection from current range start or current point
                int rangeStart = _selection.getStart();
        {
                // See whether to start selection from current range start or current point
                int rangeStart = _selection.getStart();
-               if (rangeStart < 0) {rangeStart = _selection.getCurrentPointIndex();}
+               if (rangeStart < 0 || _selection.getCurrentPointIndex() != _selection.getEnd()) {
+                       rangeStart = _selection.getCurrentPointIndex();
+               }
                selectPoint(inPointNum);
                if (rangeStart < inPointNum) {
                        _selection.selectRange(rangeStart, inPointNum);
                selectPoint(inPointNum);
                if (rangeStart < inPointNum) {
                        _selection.selectRange(rangeStart, inPointNum);
index 3c97a6d79c21e52ac1c7adc430d7999a6a7167f7..e0334b583ead9ff891aabb13a2f4edac69a4c091 100644 (file)
@@ -11,7 +11,12 @@ import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyEvent;
 import java.awt.event.KeyListener;
+import java.io.ByteArrayOutputStream;
+import java.io.File;
+import java.io.FileInputStream;
+import java.io.IOException;
 import java.io.InputStream;
 import java.io.InputStream;
+import java.util.zip.GZIPInputStream;
 
 import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
 
 import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
@@ -29,6 +34,7 @@ import tim.prune.ExternalTools;
 import tim.prune.GenericFunction;
 import tim.prune.GpsPruner;
 import tim.prune.I18nManager;
 import tim.prune.GenericFunction;
 import tim.prune.GpsPruner;
 import tim.prune.I18nManager;
+import tim.prune.jpeg.ExifGateway;
 import tim.prune.threedee.WindowFactory;
 
 /**
 import tim.prune.threedee.WindowFactory;
 
 /**
@@ -144,6 +150,13 @@ public class AboutScreen extends GenericFunction
                        new JLabel(I18nManager.getText("dialog.about.systeminfo.gnuplot") + " : "),
                        0, 5);
                addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[3], 1, 5);
                        new JLabel(I18nManager.getText("dialog.about.systeminfo.gnuplot") + " : "),
                        0, 5);
                addToGridBagPanel(sysInfoPanel, gridBag, constraints, _installedLabels[3], 1, 5);
+               // Exif library
+               addToGridBagPanel(sysInfoPanel, gridBag, constraints,
+                       new JLabel(I18nManager.getText("dialog.about.systeminfo.exiflib") + " : "),
+                       0, 6);
+               final String exiflibkey = "dialog.about.systeminfo.exiflib." + ExifGateway.getDescriptionKey();
+               addToGridBagPanel(sysInfoPanel, gridBag, constraints,
+                       new JLabel(I18nManager.getText(exiflibkey)), 1, 6);
                _tabs.add(I18nManager.getText("dialog.about.systeminfo"), sysInfoPanel);
 
                // Third pane for credits
                _tabs.add(I18nManager.getText("dialog.about.systeminfo"), sysInfoPanel);
 
                // Third pane for credits
@@ -178,32 +191,35 @@ public class AboutScreen extends GenericFunction
                        new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
                        1, 3);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Ramon, Miguel, In\u00E9s, Piotr, Petrovsk, Josatoc, Weehal,"),
                        1, 3);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
-                       new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko, katpatuka"),
+                       new JLabel(" theYinYeti, Rothermographer, Sam, Rudolph, nazotoko,"),
                        1, 4);
                        1, 4);
+               addToGridBagPanel(creditsPanel, gridBag, constraints,
+                       new JLabel(" katpatuka, R\u00E9mi"),
+                       1, 5);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.translations") + " : "),
-                       0, 5);
+                       0, 6);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Open Office, Gpsdrive, Babelfish, Leo, Launchpad"),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Open Office, Gpsdrive, Babelfish, Leo, Launchpad"),
-                       1, 5);
+                       1, 6);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.devtools") + " : "),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.devtools") + " : "),
-                       0, 6);
+                       0, 7);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Debian Linux, Sun Java, Eclipse, Svn, Gimp, Inkscape"),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Debian Linux, Sun Java, Eclipse, Svn, Gimp, Inkscape"),
-                       1, 6);
+                       1, 7);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.othertools") + " : "),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.othertools") + " : "),
-                       0, 7);
+                       0, 8);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Openstreetmap, Povray, Exiftool, Google Earth, Gpsbabel, Gnuplot"),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Openstreetmap, Povray, Exiftool, Google Earth, Gpsbabel, Gnuplot"),
-                       1, 7);
+                       1, 8);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.thanks") + " : "),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel(I18nManager.getText("dialog.about.credits.thanks") + " : "),
-                       0, 8);
+                       0, 9);
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Friends and loved ones, for encouragement and support"),
                addToGridBagPanel(creditsPanel, gridBag, constraints,
                        new JLabel("Friends and loved ones, for encouragement and support"),
-                       1, 8);
+                       1, 9);
                _tabs.add(I18nManager.getText("dialog.about.credits"), creditsPanel);
 
                // Read me
                _tabs.add(I18nManager.getText("dialog.about.credits"), creditsPanel);
 
                // Read me
@@ -271,6 +287,9 @@ public class AboutScreen extends GenericFunction
         */
        private String getReadmeText()
        {
         */
        private String getReadmeText()
        {
+               // First, try locally-held readme.txt if available (as it normally should be)
+               // Readme file can either be in file system or packed in the same jar as code
+               String errorMessage = null;
                try
                {
                        // For some reason using ../readme.txt doesn't work, so need absolute path
                try
                {
                        // For some reason using ../readme.txt doesn't work, so need absolute path
@@ -278,11 +297,39 @@ public class AboutScreen extends GenericFunction
                        if (in != null) {
                                byte[] buffer = new byte[in.available()];
                                in.read(buffer);
                        if (in != null) {
                                byte[] buffer = new byte[in.available()];
                                in.read(buffer);
+                               in.close();
                                return new String(buffer);
                        }
                }
                                return new String(buffer);
                        }
                }
-               catch (java.io.IOException e) {
-                       System.err.println("Exception trying to get readme : " + e.getMessage());
+               catch (IOException e) {
+                       errorMessage =  e.getMessage();
+               }
+               // Locally-held file failed, so try to find gz file installed on system (eg Debian)
+               try
+               {
+                       File gzFile = new File("/usr/share/doc/gpsprune/readme.txt.gz");
+                       if (gzFile.exists())
+                       {
+                               // Copy decompressed bytes from gz file into out
+                               InputStream in = new GZIPInputStream(new FileInputStream(gzFile));
+                               ByteArrayOutputStream out = new ByteArrayOutputStream();
+                               byte[] buffer = new byte[8 * 1024];
+                               int count = 0;
+                               do {
+                                       out.write(buffer, 0, count);
+                                       count = in.read(buffer, 0, buffer.length);
+                               } while (count != -1);
+                               out.close();
+                               in.close();
+                               return out.toString();
+                       }
+               }
+               catch (IOException e) {
+                       System.err.println("Exception trying to get readme.gz : " + e.getMessage());
+               }
+               // Only show first error message if couldn't get readme from gz either
+               if (errorMessage != null) {
+                       System.err.println("Exception trying to get readme: " + errorMessage);
                }
                return I18nManager.getText("error.readme.notfound");
        }
                }
                return I18nManager.getText("error.readme.notfound");
        }
diff --git a/tim/prune/function/AddMapSourceDialog.java b/tim/prune/function/AddMapSourceDialog.java
new file mode 100644 (file)
index 0000000..d7126ea
--- /dev/null
@@ -0,0 +1,309 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.CardLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.GridLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import javax.swing.BorderFactory;
+import javax.swing.ButtonGroup;
+import javax.swing.JButton;
+import javax.swing.JComboBox;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JRadioButton;
+import javax.swing.JTextField;
+
+import tim.prune.I18nManager;
+import tim.prune.gui.map.CloudmadeMapSource;
+import tim.prune.gui.map.MapSource;
+import tim.prune.gui.map.MapSourceLibrary;
+import tim.prune.gui.map.OsmMapSource;
+
+/**
+ * Class to handle the adding of a new map source
+ */
+public class AddMapSourceDialog
+{
+       private SetMapBgFunction _parent = null;
+       private JDialog _addDialog = null;
+       private JRadioButton[] _typeRadios = null;
+       private JPanel _cards = null;
+       // controls for osm panel
+       private JTextField _oNameField = null;
+       private JTextField _baseUrlField = null, _topUrlField = null;
+       private JComboBox _oZoomCombo = null;
+       // controls for cloudmade panel
+       private JTextField _cNameField = null;
+       private JTextField _cStyleField = null;
+       private JComboBox _cZoomCombo = null;
+       private JButton _okButton = null;
+
+
+       /**
+        * Constructor
+        * @param inParent parent dialog
+        */
+       public AddMapSourceDialog(JDialog inParentDialog, SetMapBgFunction inParentFunction)
+       {
+               _parent = inParentFunction;
+               _addDialog = new JDialog(inParentDialog, I18nManager.getText("dialog.addmapsource.title"), true);
+               _addDialog.add(makeDialogComponents());
+               _addDialog.setLocationRelativeTo(inParentDialog);
+               _addDialog.pack();
+       }
+
+
+       /**
+        * Create dialog components
+        * @return Panel containing all gui elements in dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout());
+               // Top panel with two radio buttons to select source type
+               JPanel radioPanel = new JPanel();
+               ButtonGroup radioGroup = new ButtonGroup();
+               radioPanel.setLayout(new GridLayout(1, 0));
+               _typeRadios = new JRadioButton[2];
+               _typeRadios[0] = new JRadioButton("Openstreetmap");
+               radioGroup.add(_typeRadios[0]);
+               radioPanel.add(_typeRadios[0]);
+               _typeRadios[1] = new JRadioButton("Cloudmade");
+               radioGroup.add(_typeRadios[1]);
+               radioPanel.add(_typeRadios[1]);
+               _typeRadios[0].setSelected(true);
+               // listener for clicks on type radios
+               ActionListener typeListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               CardLayout cl = (CardLayout) _cards.getLayout();
+                               if (_typeRadios[0].isSelected()) {cl.first(_cards);}
+                               else {cl.last(_cards);}
+                               enableOK();
+                       }
+               };
+               _typeRadios[0].addActionListener(typeListener);
+               _typeRadios[1].addActionListener(typeListener);
+               radioPanel.setBorder(BorderFactory.createEmptyBorder(5, 5, 5, 5));
+               dialogPanel.add(radioPanel, BorderLayout.NORTH);
+
+               _cards = new JPanel();
+               _cards.setLayout(new CardLayout());
+               // listener
+               KeyAdapter keyListener = new KeyAdapter() {
+                       public void keyReleased(KeyEvent e) {
+                               super.keyReleased(e);
+                               enableOK();
+                       }
+               };
+               // openstreetmap panel
+               JPanel osmPanel = new JPanel();
+               osmPanel.setLayout(new GridLayout(0, 2, 5, 5));
+               osmPanel.setBorder(BorderFactory.createEmptyBorder(6, 2, 4, 2));
+               osmPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.sourcename")));
+               _oNameField = new JTextField(18);
+               _oNameField.addKeyListener(keyListener);
+               osmPanel.add(_oNameField);
+               // Base layer
+               osmPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.layer1url")));
+               _baseUrlField = new JTextField(18);
+               _baseUrlField.addKeyListener(keyListener);
+               osmPanel.add(_baseUrlField);
+               // Top layer
+               osmPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.layer2url")));
+               _topUrlField = new JTextField(18);
+               _topUrlField.addKeyListener(keyListener);
+               osmPanel.add(_topUrlField);
+               // Max zoom
+               osmPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.maxzoom")));
+               _oZoomCombo = new JComboBox();
+               for (int i=10; i<=20; i++) {
+                       _oZoomCombo.addItem("" + i);
+               }
+               osmPanel.add(_oZoomCombo);
+               _cards.add(osmPanel, "card1");
+               // Panel for cloudmade source
+               JPanel cloudPanel = new JPanel();
+               cloudPanel.setLayout(new GridLayout(0, 2, 5, 5));
+               cloudPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.sourcename")));
+               _cNameField = new JTextField(18);
+               _cNameField.addKeyListener(keyListener);
+               cloudPanel.add(_cNameField);
+               cloudPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.cloudstyle")));
+               _cStyleField = new JTextField(18);
+               _cStyleField.addKeyListener(keyListener);
+               cloudPanel.add(_cStyleField);
+               cloudPanel.add(new JLabel(I18nManager.getText("dialog.addmapsource.maxzoom")));
+               _cZoomCombo = new JComboBox();
+               for (int i=10; i<=20; i++) {
+                       _cZoomCombo.addItem("" + i);
+               }
+               cloudPanel.add(_cZoomCombo);
+               cloudPanel.add(new JLabel(" ")); // force four rows to space text boxes properly
+               _cards.add(cloudPanel, "card2");
+               // cards
+               JPanel holderPanel = new JPanel();
+               holderPanel.setLayout(new BorderLayout());
+               holderPanel.add(_cards, BorderLayout.NORTH);
+               dialogPanel.add(holderPanel, BorderLayout.CENTER);
+
+               // button panel at bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               ActionListener okListener = new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               finish();
+                       }
+               };
+               _okButton.addActionListener(okListener);
+               buttonPanel.add(_okButton);
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _addDialog.dispose();
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               return dialogPanel;
+       }
+
+
+       /**
+        * Init and show the dialog
+        */
+       public void showDialog()
+       {
+               _oNameField.setText("");
+               _baseUrlField.setText("");
+               _topUrlField.setText("");
+               _oZoomCombo.setSelectedIndex(8);
+               _cNameField.setText("");
+               _cStyleField.setText("");
+               _cZoomCombo.setSelectedIndex(8);
+               _okButton.setEnabled(false);
+               _addDialog.setVisible(true);
+       }
+
+
+       /**
+        * Check the currently entered details and enable the OK button if it looks OK
+        */
+       private void enableOK()
+       {
+               boolean ok = false;
+               if (_typeRadios[0].isSelected()) {ok = isOsmPanelOk();}
+               if (_typeRadios[1].isSelected()) {ok = isCloudPanelOk();}
+               _okButton.setEnabled(ok);
+       }
+
+       /**
+        * Check the openstreetmap panel if all details are complete
+        * @return true if details look ok
+        */
+       private boolean isOsmPanelOk()
+       {
+               boolean ok = _oNameField.getText().trim().length() > 1;
+               URL baseUrl = null, topUrl = null;
+               try {
+                       // Try to parse base url if given
+                       String baseText = _baseUrlField.getText().trim();
+                       if (baseText.length() > 10) {
+                               baseUrl = new URL(baseText);
+                       }
+                       else if (baseText.length() > 0) {ok = false;}
+                       // Same again for top url if given
+                       String topText = _topUrlField.getText().trim();
+                       if (topText.length() > 10) {
+                               topUrl = new URL(topText);
+                       }
+                       else if (topText.length() > 0) {ok = false;}
+               } catch (MalformedURLException e) {
+                       ok = false;
+               }
+               // looks ok if at least one url given
+               return (ok && (baseUrl != null || topUrl != null));
+       }
+
+       /**
+        * Check the cloudmade panel if all details are complete
+        * @return true if details look ok
+        */
+       private boolean isCloudPanelOk()
+       {
+               boolean ok = _cNameField.getText().trim().length() > 1;
+               int styleNum = 0;
+               try {
+                       styleNum = Integer.parseInt(_cStyleField.getText());
+               }
+               catch (NumberFormatException nfe) {}
+               return (ok && styleNum > 0);
+       }
+
+       /**
+        * Finish by adding the requested source and refreshing the parent
+        */
+       private void finish()
+       {
+               MapSource newSource = null;
+               if (_typeRadios[0].isSelected())
+               {
+                       // Openstreetmap source
+                       String sourceName = getUniqueSourcename(_oNameField.getText());
+                       String url1 = _baseUrlField.getText().trim();
+                       String url2 = _topUrlField.getText().trim();
+                       newSource = new OsmMapSource(sourceName, url1, url2, _oZoomCombo.getSelectedIndex()+10);
+               }
+               else if (_typeRadios[1].isSelected())
+               {
+                       String sourceName = getUniqueSourcename(_cNameField.getText());
+                       newSource = new CloudmadeMapSource(sourceName, _cStyleField.getText(),
+                               _cZoomCombo.getSelectedIndex()+10);
+               }
+               // Add new source if ok
+               if (newSource != null)
+               {
+                       MapSourceLibrary.addSource(newSource);
+                       // inform setmapbg dialog
+                       _parent.updateList();
+                       _addDialog.setVisible(false);
+               }
+       }
+
+       /**
+        * Check the given source name if it exists in library already
+        * @param inName name to check
+        * @return unique name not yet in library
+        */
+       private static String getUniqueSourcename(String inName)
+       {
+               String name = inName;
+               if (name == null) {name = "";}
+               else {name = name.trim();}
+               if (name.equals("")) {
+                       name = I18nManager.getText("dialog.addmapsource.noname");
+               }
+               // Check there isn't already a map source with this name
+               if (MapSourceLibrary.hasSourceName(name))
+               {
+                       int suffix = 1;
+                       while (MapSourceLibrary.hasSourceName(name + suffix)) {
+                               suffix++;
+                       }
+                       name += suffix;
+               }
+               return name;
+       }
+}
diff --git a/tim/prune/function/DiskCacheConfig.java b/tim/prune/function/DiskCacheConfig.java
new file mode 100644 (file)
index 0000000..58643d1
--- /dev/null
@@ -0,0 +1,212 @@
+package tim.prune.function;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.KeyAdapter;
+import java.awt.event.KeyEvent;
+import java.io.File;
+
+import javax.swing.JButton;
+import javax.swing.JCheckBox;
+import javax.swing.JDialog;
+import javax.swing.JFileChooser;
+import javax.swing.JLabel;
+import javax.swing.JOptionPane;
+import javax.swing.JPanel;
+import javax.swing.JTextField;
+
+import tim.prune.App;
+import tim.prune.DataSubscriber;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.config.Config;
+
+/**
+ * Class to show the popup window for setting the path to disk cache
+ */
+public class DiskCacheConfig extends GenericFunction
+{
+       private JDialog _dialog = null;
+       private JCheckBox _cacheCheckbox = null;
+       private JTextField _cacheDirBox = null;
+       private JButton _browseButton = null;
+       private JButton _okButton = null;
+       private boolean _initialCheckState = false;
+       private String _initialCacheDir = null;
+
+       /**
+        * Constructor
+        * @param inApp app object
+        */
+       public DiskCacheConfig(App inApp)
+       {
+               super(inApp);
+       }
+
+       /**
+        * Return the name key for this function
+        */
+       public String getNameKey()
+       {
+               return "function.diskcache";
+       }
+
+       /**
+        * @return the contents of the window as a Component
+        */
+       private Component makeContents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout(0, 5));
+               // top panel
+               JPanel topPanel = new JPanel();
+               _cacheCheckbox = new JCheckBox(I18nManager.getText("dialog.diskcache.save"));
+               _cacheCheckbox.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               enableOk();
+                       }
+               });
+               topPanel.add(_cacheCheckbox);
+               dialogPanel.add(topPanel, BorderLayout.NORTH);
+               // dir panel
+               JPanel dirPanel = new JPanel();
+               dirPanel.setLayout(new BorderLayout());
+               dirPanel.add(new JLabel(I18nManager.getText("dialog.diskcache.dir")), BorderLayout.WEST);
+               _cacheDirBox = new JTextField(24);
+               _cacheDirBox.addKeyListener(new KeyAdapter() {
+                       public void keyReleased(KeyEvent arg0) {
+                               super.keyReleased(arg0);
+                               enableOk();
+                       }
+               });
+               dirPanel.add(_cacheDirBox, BorderLayout.CENTER);
+               _browseButton = new JButton(I18nManager.getText("button.browse"));
+               _browseButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               chooseDir();
+                       }
+               });
+               dirPanel.add(_browseButton, BorderLayout.EAST);
+               dialogPanel.add(dirPanel, BorderLayout.CENTER);
+
+               // Cancel button at the bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               _okButton = new JButton(I18nManager.getText("button.ok"));
+               _okButton.addActionListener(new ActionListener()
+               {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               finish();
+                       }
+               });
+               buttonPanel.add(_okButton);
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               _dialog.dispose();
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               return dialogPanel;
+       }
+
+       /**
+        * Enable or disable the ok button according to what's changed
+        */
+       private void enableOk()
+       {
+               boolean checkState = _cacheCheckbox.isSelected();
+               _cacheDirBox.setEditable(checkState);
+               _browseButton.setEnabled(checkState);
+               boolean ok = false;
+               // If checkbox has stayed off then disable ok
+               if (!_initialCheckState && !checkState) {ok = false;}
+               else {
+                       // If checkbox has been switched off then enable
+                       if (!checkState) {ok = true;}
+                       else {
+                               // checkbox is on, check value
+                               String path = _cacheDirBox.getText();
+                               if (path.equals("") || (_initialCacheDir != null && path.equals(_initialCacheDir))) {
+                                       // Value blank or same as before
+                                       ok = false;
+                               }
+                               else {
+                                       ok = true;
+                               }
+                       }
+               }
+               _okButton.setEnabled(ok);
+       }
+
+       /**
+        * Show window
+        */
+       public void begin()
+       {
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()));
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.getContentPane().add(makeContents());
+                       _dialog.pack();
+               }
+               // Set controls according to current config
+               String currPath = Config.getConfigString(Config.KEY_DISK_CACHE);
+               _cacheCheckbox.setSelected(currPath != null);
+               _cacheDirBox.setText(currPath==null?"":currPath);
+               enableOk();
+               // Remember current state
+               _initialCheckState = _cacheCheckbox.isSelected();
+               _dialog.setVisible(true);
+       }
+
+       /**
+        * Function activated by the "Browse..." button to select a directory for the cache
+        */
+       private void chooseDir()
+       {
+               JFileChooser chooser = new JFileChooser();
+               chooser.setFileSelectionMode(JFileChooser.DIRECTORIES_ONLY);
+               // Set start path from currently selected dir
+               String path = _cacheDirBox.getText();
+               if (path.length() > 1) {chooser.setCurrentDirectory(new File(path));}
+               if (chooser.showOpenDialog(_parentFrame) == JFileChooser.APPROVE_OPTION)
+               {
+                       _cacheDirBox.setText(chooser.getSelectedFile().getAbsolutePath());
+               }
+               enableOk();
+       }
+
+       /**
+        * OK pressed, save selected settings in Config
+        */
+       private void finish()
+       {
+               String cachePath = (_cacheCheckbox.isSelected()?_cacheDirBox.getText():null);
+               // Create dir if it doesn't exist already and creation confirmed
+               if (cachePath != null)
+               {
+                       File cacheDir = new File(cachePath);
+                       if ((!cacheDir.exists() || !cacheDir.isDirectory()) && (JOptionPane.showConfirmDialog(_dialog,
+                               I18nManager.getText("dialog.diskcache.createdir") + ": " + cacheDir.getAbsolutePath() + " ?",
+                               I18nManager.getText(getNameKey()), JOptionPane.OK_CANCEL_OPTION) == JOptionPane.CANCEL_OPTION || !cacheDir.mkdir()))
+                       {
+                               JOptionPane.showMessageDialog(_dialog, I18nManager.getText("dialog.diskcache.nocreate"),
+                                       I18nManager.getText(getNameKey()), JOptionPane.WARNING_MESSAGE);
+                               return;
+                       }
+               }
+               Config.setConfigString(Config.KEY_DISK_CACHE, cachePath);
+               // inform subscribers so that tiles are wiped from memory and refetched
+               UpdateMessageBroker.informSubscribers(DataSubscriber.MAPSERVER_CHANGED);
+               _dialog.dispose();
+       }
+}
index ed86ef90ec54e75e7da713bd87f6424e8f051d66..338bf0bebbe1e1aef4d0130cf9b5d904b9c1a5c5 100644 (file)
@@ -22,6 +22,7 @@ import tim.prune.data.Altitude;
 import tim.prune.data.Distance;
 import tim.prune.data.Selection;
 import tim.prune.gui.DisplayUtils;
 import tim.prune.data.Distance;
 import tim.prune.data.Selection;
 import tim.prune.gui.DisplayUtils;
+import tim.prune.gui.profile.SpeedData;
 
 /**
  * Class to show the full range details in a separate popup
 
 /**
  * Class to show the full range details in a separate popup
@@ -38,6 +39,7 @@ public class FullRangeDetails extends GenericFunction
        private JLabel _gradientLabel = null;
        /** Moving distance, speed */
        private JLabel _movingDistanceLabel = null, _aveMovingSpeedLabel = null;
        private JLabel _gradientLabel = null;
        /** Moving distance, speed */
        private JLabel _movingDistanceLabel = null, _aveMovingSpeedLabel = null;
+       private JLabel _maxSpeedLabel = null;
        /** Number formatter for one decimal place */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
        /** Flexible number formatter for different decimal places */
        /** Number formatter for one decimal place */
        private static final NumberFormat FORMAT_ONE_DP = NumberFormat.getNumberInstance();
        /** Flexible number formatter for different decimal places */
@@ -123,6 +125,12 @@ public class FullRangeDetails extends GenericFunction
                midPanel.add(movingSpeedLabel);
                _aveMovingSpeedLabel = new JLabel("5 km/h");
                midPanel.add(_aveMovingSpeedLabel);
                midPanel.add(movingSpeedLabel);
                _aveMovingSpeedLabel = new JLabel("5 km/h");
                midPanel.add(_aveMovingSpeedLabel);
+               // Maximum speed
+               JLabel maxSpeedLabel = new JLabel(I18nManager.getText("details.range.maxspeed") + ": ");
+               maxSpeedLabel.setHorizontalAlignment(JLabel.RIGHT);
+               midPanel.add(maxSpeedLabel);
+               _maxSpeedLabel = new JLabel("10 km/h");
+               midPanel.add(_maxSpeedLabel);
 
                dialogPanel.add(midPanel, BorderLayout.CENTER);
                // button panel at bottom
 
                dialogPanel.add(midPanel, BorderLayout.CENTER);
                // button panel at bottom
@@ -194,6 +202,22 @@ public class FullRangeDetails extends GenericFunction
                else {
                        _aveMovingSpeedLabel.setText("");
                }
                else {
                        _aveMovingSpeedLabel.setText("");
                }
+
+               // Maximum speed
+               SpeedData speeds = new SpeedData(_app.getTrackInfo().getTrack());
+               speeds.init();
+               double maxSpeed = 0.0;
+               for (int i=selection.getStart(); i<=selection.getEnd(); i++) {
+                       if (speeds.hasData(i) && (speeds.getData(i) > maxSpeed)) {
+                               maxSpeed = speeds.getData(i);
+                       }
+               }
+               if (maxSpeed > 0.0) {
+                       _maxSpeedLabel.setText(roundedNumber(maxSpeed) + " " + speedUnitsStr);
+               }
+               else {
+                       _maxSpeedLabel.setText("");
+               }
        }
 
        /**
        }
 
        /**
diff --git a/tim/prune/function/MapSourceListModel.java b/tim/prune/function/MapSourceListModel.java
new file mode 100644 (file)
index 0000000..4548cc4
--- /dev/null
@@ -0,0 +1,47 @@
+package tim.prune.function;
+
+import javax.swing.AbstractListModel;
+
+import tim.prune.gui.map.MapSource;
+import tim.prune.gui.map.MapSourceLibrary;
+
+/**
+ * Class to act as list model for the map source list
+ */
+public class MapSourceListModel extends AbstractListModel
+{
+       /**
+        * @see javax.swing.ListModel#getSize()
+        */
+       public int getSize()
+       {
+               return MapSourceLibrary.getNumSources();
+       }
+
+       /**
+        * @see javax.swing.ListModel#getElementAt(int)
+        */
+       public Object getElementAt(int inIndex)
+       {
+               if (inIndex < 0 || inIndex >= getSize()) return "";
+               return MapSourceLibrary.getSource(inIndex).getName();
+       }
+
+       /**
+        * @param inIndex index in list
+        * @return corresponding map source object
+        */
+       public MapSource getSource(int inIndex)
+       {
+               if (inIndex < 0 || inIndex >= getSize()) return null;
+               return MapSourceLibrary.getSource(inIndex);
+       }
+
+       /**
+        * Fire event to notify that contents have changed
+        */
+       public void fireChanged()
+       {
+               this.fireContentsChanged(this, 0, getSize()-1);
+       }
+}
index 1106001ad3f10abaec76c3b17a73f24d4ac543fd..23fe8d285afd8af965a47e62f3fcdc0827a12603 100644 (file)
@@ -8,6 +8,7 @@ import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 import java.awt.event.MouseAdapter;
+import java.awt.event.MouseEvent;
 
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
 
 import javax.swing.BorderFactory;
 import javax.swing.JButton;
@@ -96,12 +97,15 @@ public class PasteCoordinates extends GenericFunction
                // Listeners to enable/disable ok button
                KeyAdapter keyListener = new KeyAdapter() {
                        /** Key released */
                // Listeners to enable/disable ok button
                KeyAdapter keyListener = new KeyAdapter() {
                        /** Key released */
-                       public void keyReleased(KeyEvent arg0) {
+                       public void keyReleased(KeyEvent inE) {
                                enableOK();
                                enableOK();
+                               if (inE.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
                        }
                };
                MouseAdapter mouseListener = new MouseAdapter() {
                        }
                };
                MouseAdapter mouseListener = new MouseAdapter() {
-                       public void mouseReleased(java.awt.event.MouseEvent arg0) {
+                       public void mouseReleased(MouseEvent inE) {
                                enableOK();
                        };
                };
                                enableOK();
                        };
                };
@@ -132,7 +136,7 @@ public class PasteCoordinates extends GenericFunction
                ActionListener okListener = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                ActionListener okListener = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
-                               finish();
+                               if (_okButton.isEnabled()) {finish();}
                        }
                };
                _okButton.addActionListener(okListener);
                        }
                };
                _okButton.addActionListener(okListener);
@@ -159,7 +163,7 @@ public class PasteCoordinates extends GenericFunction
        private void enableOK()
        {
                String text = _coordField.getText();
        private void enableOK()
        {
                String text = _coordField.getText();
-               _okButton.setEnabled(text != null && text.length() > 10
+               _okButton.setEnabled(text != null && text.length() > 6
                        && (text.indexOf(' ') >= 0 || text.indexOf(',') >= 0));
        }
 
                        && (text.indexOf(' ') >= 0 || text.indexOf(',') >= 0));
        }
 
index d54e1be2cdef26eab604ce3358e059a3d839d22e..77fb091b3f939ccfbd78e7ef722b93cc5d476880 100644 (file)
@@ -43,11 +43,12 @@ public class SetLanguage extends GenericFunction
        /** Names of languages for display in dropdown (not translated) */
        private static final String[] LANGUAGE_NAMES = {"deutsch", "english", "espa\u00F1ol", "fran\u00E7ais",
                "italiano", "polski", "\u4e2d\u6587 (chinese)", "\u65E5\u672C\u8A9E (japanese)",
        /** Names of languages for display in dropdown (not translated) */
        private static final String[] LANGUAGE_NAMES = {"deutsch", "english", "espa\u00F1ol", "fran\u00E7ais",
                "italiano", "polski", "\u4e2d\u6587 (chinese)", "\u65E5\u672C\u8A9E (japanese)",
-               "schwiizerd\u00FC\u00FCtsch", "t\u00FCrk\u00E7e", "portugu\u00EAs", "bahasa indonesia", "rom\u00E2n\u0103"
+               "schwiizerd\u00FC\u00FCtsch", "t\u00FCrk\u00E7e", "portugu\u00EAs",
+               "afrikaans", "bahasa indonesia", "rom\u00E2n\u0103"
        };
        /** Associated language codes (must be in same order as names!) */
        private static final String[] LANGUAGE_CODES = {"de", "en", "es", "fr", "it", "pl", "zh", "ja",
        };
        /** Associated language codes (must be in same order as names!) */
        private static final String[] LANGUAGE_CODES = {"de", "en", "es", "fr", "it", "pl", "zh", "ja",
-               "de_ch", "tr", "pt", "in", "ro"
+               "de_ch", "tr", "pt", "af", "in", "ro"
        };
 
 
        };
 
 
index cadacf9962274010d0a4505c52bcc0f9fc739b3d..fb715b03b0b51f0f3d450bf4d4fa3ed91243b4cf 100644 (file)
@@ -2,20 +2,24 @@ package tim.prune.function;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
 
 import java.awt.BorderLayout;
 import java.awt.Component;
+import java.awt.Dimension;
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 
 import java.awt.FlowLayout;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.KeyAdapter;
 import java.awt.event.KeyEvent;
 
+import javax.swing.BorderFactory;
 import javax.swing.BoxLayout;
 import javax.swing.BoxLayout;
-import javax.swing.ButtonGroup;
 import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
 import javax.swing.JButton;
 import javax.swing.JDialog;
 import javax.swing.JLabel;
+import javax.swing.JList;
 import javax.swing.JPanel;
 import javax.swing.JPanel;
-import javax.swing.JRadioButton;
-import javax.swing.JTextField;
+import javax.swing.JScrollPane;
+import javax.swing.ListSelectionModel;
+import javax.swing.event.ListSelectionEvent;
+import javax.swing.event.ListSelectionListener;
 
 import tim.prune.App;
 import tim.prune.DataSubscriber;
 
 import tim.prune.App;
 import tim.prune.DataSubscriber;
@@ -23,6 +27,7 @@ import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.Config;
 import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.Config;
+import tim.prune.gui.map.MapSourceLibrary;
 
 /**
  * Function to set the tile server for the map backgrounds
 
 /**
  * Function to set the tile server for the map backgrounds
@@ -30,11 +35,13 @@ import tim.prune.config.Config;
 public class SetMapBgFunction extends GenericFunction
 {
        private JDialog _dialog = null;
 public class SetMapBgFunction extends GenericFunction
 {
        private JDialog _dialog = null;
+       private JList _list = null;
+       private MapSourceListModel _listModel = null;
+       private String _initialSource = null;
        private JButton _okButton = null;
        private JButton _okButton = null;
-       private JRadioButton[] _serverRadios = null;
-       private JTextField _serverUrl = null;
-       /** Index of 'other' server with freeform url */
-       private static final int OTHER_SERVER_NUM = 3;
+       private JButton _deleteButton = null;
+       // Add dialog
+       private AddMapSourceDialog _addDialog = null;
 
 
        /**
 
 
        /**
@@ -63,10 +70,10 @@ public class SetMapBgFunction extends GenericFunction
                        _dialog.setLocationRelativeTo(_parentFrame);
                        _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                        _dialog.getContentPane().add(makeDialogComponents());
                        _dialog.setLocationRelativeTo(_parentFrame);
                        _dialog.setDefaultCloseOperation(JDialog.DISPOSE_ON_CLOSE);
                        _dialog.getContentPane().add(makeDialogComponents());
-                       initValues();
                        _dialog.pack();
                }
                        _dialog.pack();
                }
-               enableOK();
+               initValues();
+               enableButtons();
                _dialog.setVisible(true);
        }
 
                _dialog.setVisible(true);
        }
 
@@ -78,39 +85,48 @@ public class SetMapBgFunction extends GenericFunction
        private Component makeDialogComponents()
        {
                JPanel dialogPanel = new JPanel();
        private Component makeDialogComponents()
        {
                JPanel dialogPanel = new JPanel();
-               dialogPanel.setLayout(new BorderLayout());
-               // Main panel
-               JPanel mainPanel = new JPanel();
-               mainPanel.setLayout(new BoxLayout(mainPanel, BoxLayout.Y_AXIS));
-               _serverRadios = new JRadioButton[4];
-               ButtonGroup serverRadioGroup = new ButtonGroup();
-               String[] serverKeys = {"dialog.setmapbg.mapnik", "dialog.setmapbg.osma",
-                       "dialog.setmapbg.cyclemap", "dialog.setmapbg.other"};
-               // action listener for radios
-               ActionListener changeListener = new ActionListener() {
-                       public void actionPerformed(ActionEvent arg0) {
-                               enableOK();
+               dialogPanel.setLayout(new BorderLayout(8, 8));
+               // intro label
+               JLabel introLabel = new JLabel(I18nManager.getText("dialog.setmapbg.intro"));
+               introLabel.setBorder(BorderFactory.createEmptyBorder(5, 4, 1, 4));
+               dialogPanel.add(introLabel, BorderLayout.NORTH);
+               // list box
+               _listModel = new MapSourceListModel();
+               _list = new JList(_listModel);
+               _list.setSelectionMode(ListSelectionModel.SINGLE_SELECTION);
+               dialogPanel.add(new JScrollPane(_list), BorderLayout.CENTER);
+               _list.addListSelectionListener(new ListSelectionListener() {
+                       public void valueChanged(ListSelectionEvent arg0) {
+                               enableButtons();
                        }
                        }
-               };
-               // Create four radio buttons
-               for (int i=0; i<4; i++)
-               {
-                       _serverRadios[i] = new JRadioButton(I18nManager.getText(serverKeys[i]));
-                       _serverRadios[i].addActionListener(changeListener);
-                       serverRadioGroup.add(_serverRadios[i]);
-                       mainPanel.add(_serverRadios[i]);
-               }
-               // entry field for other server urls
-               mainPanel.add(new JLabel(I18nManager.getText("dialog.setmapbg.server")));
-               _serverUrl = new JTextField("", 12);
-               _serverUrl.addKeyListener(new KeyAdapter() {
+               });
+               _list.addKeyListener(new KeyAdapter() {
                        public void keyReleased(KeyEvent e) {
                                super.keyReleased(e);
                        public void keyReleased(KeyEvent e) {
                                super.keyReleased(e);
-                               enableOK();
+                               if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+                                       _dialog.dispose();
+                               }
                        }
                });
                        }
                });
-               mainPanel.add(_serverUrl);
-               dialogPanel.add(mainPanel, BorderLayout.NORTH);
+               _list.setPreferredSize(new Dimension(200, 200));
+               // button panel on right
+               JPanel rightPanel = new JPanel();
+               rightPanel.setLayout(new BoxLayout(rightPanel, BoxLayout.Y_AXIS));
+               JButton addButton = new JButton(I18nManager.getText("button.addnew"));
+               addButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               addNewSource();
+                       }
+               });
+               rightPanel.add(addButton);
+               _deleteButton = new JButton(I18nManager.getText("button.delete"));
+               _deleteButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent arg0) {
+                               deleteMapSource(_list.getSelectedIndex());
+                       }
+               });
+               rightPanel.add(_deleteButton);
+               dialogPanel.add(rightPanel, BorderLayout.EAST);
 
                // button panel at bottom
                JPanel buttonPanel = new JPanel();
 
                // button panel at bottom
                JPanel buttonPanel = new JPanel();
@@ -142,49 +158,65 @@ public class SetMapBgFunction extends GenericFunction
         */
        private void initValues()
        {
         */
        private void initValues()
        {
-               // Get values from config
-               try {
-                       _serverRadios[Config.getConfigInt(Config.KEY_MAPSERVERINDEX)].setSelected(true);
-               }
-               catch (ArrayIndexOutOfBoundsException e) {} // ignore
-               String url = Config.getConfigString(Config.KEY_MAPSERVERURL);
-               if (url != null) {_serverUrl.setText(url);}
-               // Choose default if none selected
-               if (getSelectedServer() < 0) {
-                       _serverRadios[0].setSelected(true);
+               updateList();
+               // Get selected value from config
+               int currSource = Config.getConfigInt(Config.KEY_MAPSOURCE_INDEX);
+               if (currSource < 0 || currSource >= _listModel.getSize()) {
+                       currSource = 0;
                }
                }
+               _initialSource = _listModel.getSource(currSource).getSiteStrings();
+               _list.setSelectedIndex(currSource);
        }
 
        /**
        }
 
        /**
-        * @return index of selected radio button, or -1 if none
+        * @return index of selected server, or -1 if none
         */
        private int getSelectedServer()
        {
         */
        private int getSelectedServer()
        {
-               // Loop over all four radios
-               for (int i=0; i<4; i++) {
-                       if (_serverRadios[i].isSelected()) {return i;}
-               }
-               // None selected
-               return -1;
+               return _list.getSelectedIndex();
        }
 
        /**
        }
 
        /**
-        * Enable or disable the OK button according to the selection
+        * Enable or disable the buttons according to the selection
         */
         */
-       private void enableOK()
+       private void enableButtons()
        {
                int serverNum = getSelectedServer();
        {
                int serverNum = getSelectedServer();
-               _okButton.setEnabled(inputOK());
-               _serverUrl.setEnabled(serverNum == OTHER_SERVER_NUM);
+               _okButton.setEnabled(serverNum >= 0 && serverNum < _listModel.getSize()
+                       && !_listModel.getSource(serverNum).getSiteStrings().equals(_initialSource));
+               _deleteButton.setEnabled(serverNum >= MapSourceLibrary.getNumFixedSources()
+                       && serverNum < _listModel.getSize());
        }
 
        /**
        }
 
        /**
-        * @return true if inputs are ok
+        * Start the dialog to add a new map source to the list
         */
         */
-       private boolean inputOK()
+       private void addNewSource()
        {
        {
-               int serverNum = getSelectedServer();
-               return serverNum >= 0 && (serverNum != OTHER_SERVER_NUM || _serverUrl.getText().length() > 4);
+               if (_addDialog == null) {
+                       _addDialog = new AddMapSourceDialog(_dialog, this);
+               }
+               _addDialog.showDialog();
+       }
+
+       /**
+        * Delete the selected map source so it is no longer available
+        * @param inIndex index within list
+        */
+       private void deleteMapSource(int inIndex)
+       {
+               MapSourceLibrary.deleteSource(inIndex);
+               updateList();
+               enableButtons();
+       }
+
+       /**
+        * use the library to update the current list, after add or delete
+        */
+       public void updateList()
+       {
+               _listModel.fireChanged();
+               Config.setConfigString(Config.KEY_MAPSOURCE_LIST, MapSourceLibrary.getConfigString());
        }
 
        /**
        }
 
        /**
@@ -193,9 +225,8 @@ public class SetMapBgFunction extends GenericFunction
        private void finish()
        {
                int serverNum = getSelectedServer();
        private void finish()
        {
                int serverNum = getSelectedServer();
-               if (!inputOK()) {serverNum = 0;}
-               Config.setConfigInt(Config.KEY_MAPSERVERINDEX, serverNum);
-               Config.setConfigString(Config.KEY_MAPSERVERURL, _serverUrl.getText());
+               if (serverNum < 0) {serverNum = 0;}
+               Config.setConfigInt(Config.KEY_MAPSOURCE_INDEX, serverNum);
                UpdateMessageBroker.informSubscribers(DataSubscriber.MAPSERVER_CHANGED);
                _dialog.dispose();
        }
                UpdateMessageBroker.informSubscribers(DataSubscriber.MAPSERVER_CHANGED);
                _dialog.dispose();
        }
index 3ded22310994a6850a033423fb3d546f979db4d1..a5131af7f8aa960b56c3bcc108f795c857cbc0ac 100644 (file)
@@ -87,7 +87,10 @@ public class SetPathsFunction extends GenericFunction
 
                // Main panel with edit boxes for paths
                JPanel mainPanel = new JPanel();
 
                // Main panel with edit boxes for paths
                JPanel mainPanel = new JPanel();
-               mainPanel.setLayout(new GridLayout(3, 3, 10, 1));
+               mainPanel.setLayout(new GridLayout(NUM_KEYS+1, 3, 10, 1));
+               mainPanel.add(new JLabel(" "));
+               mainPanel.add(new JLabel(" "));
+               mainPanel.add(new JLabel(I18nManager.getText("dialog.setpaths.found")));
                _editFields = new JTextField[NUM_KEYS];
                _installedLabels = new JLabel[NUM_KEYS];
                for (int i=0; i<NUM_KEYS; i++)
                _editFields = new JTextField[NUM_KEYS];
                _installedLabels = new JLabel[NUM_KEYS];
                for (int i=0; i<NUM_KEYS; i++)
@@ -147,7 +150,7 @@ public class SetPathsFunction extends GenericFunction
                for (int i=0; i<NUM_KEYS; i++)
                {
                        String command = _editFields[i].getText();
                for (int i=0; i<NUM_KEYS; i++)
                {
                        String command = _editFields[i].getText();
-                       _installedLabels[i].setText(ExternalTools.isToolInstalled(i, command)?yesText:noText);
+                       _installedLabels[i].setText("   " + (ExternalTools.isToolInstalled(i, command)?yesText:noText));
                }
        }
 
                }
        }
 
index 4b3fd370ee9c6866d6280236127c5a94881914b8..3edb4753aceabdd648b9b0a6254c6a5351f33132 100644 (file)
@@ -189,14 +189,6 @@ public class Charter extends GenericFunction
                // button panel on bottom
                JPanel buttonPanel = new JPanel();
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
                // button panel on bottom
                JPanel buttonPanel = new JPanel();
                buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
-               // Cancel button
-               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
-               cancelButton.addActionListener(new ActionListener() {
-                       public void actionPerformed(ActionEvent e) {
-                               _dialog.setVisible(false);
-                       }
-               });
-               buttonPanel.add(cancelButton);
                // ok button
                JButton okButton = new JButton(I18nManager.getText("button.ok"));
                okButton.addActionListener(new ActionListener() {
                // ok button
                JButton okButton = new JButton(I18nManager.getText("button.ok"));
                okButton.addActionListener(new ActionListener() {
@@ -206,6 +198,14 @@ public class Charter extends GenericFunction
                        }
                });
                buttonPanel.add(okButton);
                        }
                });
                buttonPanel.add(okButton);
+               // Cancel button
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               _dialog.setVisible(false);
+                       }
+               });
+               buttonPanel.add(cancelButton);
                dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
                return dialogPanel;
        }
                dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
                return dialogPanel;
        }
@@ -526,6 +526,7 @@ public class Charter extends GenericFunction
                ChartSeries values = new ChartSeries(inTrack.getNumPoints());
                DataPoint prevPoint = null, currPoint = null, nextPoint = null;
                DataPoint[] points = getDataPoints(inTrack, false);
                ChartSeries values = new ChartSeries(inTrack.getNumPoints());
                DataPoint prevPoint = null, currPoint = null, nextPoint = null;
                DataPoint[] points = getDataPoints(inTrack, false);
+               final boolean useMetric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
                // Loop over collected points
                for (int i=1; i<(points.length-1); i++)
                {
                // Loop over collected points
                for (int i=1; i<(points.length-1); i++)
                {
@@ -541,7 +542,7 @@ public class Charter extends GenericFunction
                                        + DataPoint.calculateRadiansBetween(currPoint, nextPoint);
                                double time = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp()) / 60.0 / 60.0;
                                // Convert to distance and pass to chartseries
                                        + DataPoint.calculateRadiansBetween(currPoint, nextPoint);
                                double time = nextPoint.getTimestamp().getSecondsSince(prevPoint.getTimestamp()) / 60.0 / 60.0;
                                // Convert to distance and pass to chartseries
-                               if (Config.getConfigBoolean(Config.KEY_METRIC_UNITS)) {
+                               if (useMetric) {
                                        values.setData(i, Distance.convertRadiansToDistance(rads, Units.KILOMETRES) / time);
                                } else {
                                        values.setData(i, Distance.convertRadiansToDistance(rads, Units.MILES) / time);
                                        values.setData(i, Distance.convertRadiansToDistance(rads, Units.KILOMETRES) / time);
                                } else {
                                        values.setData(i, Distance.convertRadiansToDistance(rads, Units.MILES) / time);
diff --git a/tim/prune/function/srtm/LookupSrtmFunction.java b/tim/prune/function/srtm/LookupSrtmFunction.java
new file mode 100644 (file)
index 0000000..30183d2
--- /dev/null
@@ -0,0 +1,282 @@
+package tim.prune.function.srtm;
+
+import java.awt.BorderLayout;
+import java.awt.Component;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.io.IOException;
+import java.net.URL;
+import java.util.ArrayList;
+import java.util.zip.ZipEntry;
+import java.util.zip.ZipInputStream;
+
+import javax.swing.JButton;
+import javax.swing.JDialog;
+import javax.swing.JLabel;
+import javax.swing.JPanel;
+import javax.swing.JProgressBar;
+
+import tim.prune.App;
+import tim.prune.DataSubscriber;
+import tim.prune.GenericFunction;
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
+import tim.prune.data.Track;
+import tim.prune.undo.UndoLookupSrtm;
+
+/**
+ * Class to provide a lookup function for point altitudes
+ * using the Space Shuttle's SRTM data files.
+ * HGT files are downloaded into memory via HTTP and point altitudes
+ * can then be interpolated from the 3m grid data.
+ */
+public class LookupSrtmFunction extends GenericFunction implements Runnable
+{
+       /** function dialog */
+       private JDialog _dialog = null;
+       /** Progress bar for function */
+       private JProgressBar _progressBar = null;
+       /** Cancel flag */
+       private boolean _cancelled = false;
+
+       /** Expected size of hgt file in bytes */
+       private static final long HGT_SIZE = 2884802L;
+       /** Altitude below which is considered void */
+       private static final int VOID_VAL = -32768;
+
+       /**
+        * Constructor
+        * @param inApp App object
+        */
+       public LookupSrtmFunction(App inApp)
+       {
+               super(inApp);
+       }
+
+       /** @return name key */
+       public String getNameKey() {
+               return "function.lookupsrtm";
+       }
+
+       /**
+        * Begin the lookup
+        */
+       public void begin()
+       {
+               if (_dialog == null)
+               {
+                       _dialog = new JDialog(_parentFrame, I18nManager.getText(getNameKey()), false);
+                       _dialog.setLocationRelativeTo(_parentFrame);
+                       _dialog.getContentPane().add(makeDialogComponents());
+                       _dialog.pack();
+               }
+               _progressBar.setMinimum(0);
+               _progressBar.setMaximum(100);
+               _progressBar.setValue(20);
+               _cancelled = false;
+               // start new thread for time-consuming part
+               new Thread(this).start();
+       }
+
+
+       /**
+        * Make the dialog components
+        * @return the GUI components for the dialog
+        */
+       private Component makeDialogComponents()
+       {
+               JPanel dialogPanel = new JPanel();
+               dialogPanel.setLayout(new BorderLayout());
+               dialogPanel.add(new JLabel(I18nManager.getText("confirm.running")), BorderLayout.NORTH);
+               _progressBar = new JProgressBar();
+               _progressBar.setPreferredSize(new Dimension(250, 30));
+               dialogPanel.add(_progressBar, BorderLayout.CENTER);
+               // Cancel button at the bottom
+               JPanel buttonPanel = new JPanel();
+               buttonPanel.setLayout(new FlowLayout(FlowLayout.RIGHT));
+               JButton cancelButton = new JButton(I18nManager.getText("button.cancel"));
+               cancelButton.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               _cancelled = true;
+                       }
+               });
+               buttonPanel.add(cancelButton);
+               dialogPanel.add(buttonPanel, BorderLayout.SOUTH);
+               return dialogPanel;
+       }
+
+       /**
+        * Run method using separate thread
+        */
+       public void run()
+       {
+               _dialog.setVisible(true);
+               // Compile list of tiles to get
+               Track track = _app.getTrackInfo().getTrack();
+               ArrayList<SrtmTile> tileList = new ArrayList<SrtmTile>();
+               for (int i=0; i<track.getNumPoints(); i++)
+               {
+                       // Only consider points which don't have altitudes already
+                       if (!track.getPoint(i).hasAltitude())
+                       {
+                               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);}
+                       }
+               }
+               UndoLookupSrtm undo = new UndoLookupSrtm(_app.getTrackInfo());
+               int numAltitudesFound = 0;
+               // Update progress bar
+               _progressBar.setMaximum(tileList.size());
+               _progressBar.setIndeterminate(tileList.size() <= 1);
+               _progressBar.setValue(0);
+               // Get urls for each tile
+               URL[] urls = TileFinder.getUrls(tileList);
+               for (int t=0; t<tileList.size() && !_cancelled; t++)
+               {
+                       if (urls[t] != null)
+                       {
+                               SrtmTile tile = tileList.get(t);
+                               // System.out.println("tile " + t + " of " + tileList.size() + " = " + urls[t].toString());
+                               try {
+                                       _progressBar.setValue(t);
+                                       final int ARRLENGTH = 1201*1201;
+                                       int[] heights = new int[ARRLENGTH];
+                                       // Open zipinputstream on url and check size
+                                       ZipInputStream inStream = new ZipInputStream(urls[t].openStream());
+                                       ZipEntry entry = inStream.getNextEntry();
+                                       boolean entryOk = (entry.getSize() == HGT_SIZE);
+                                       if (entryOk)
+                                       {
+                                               // Read entire file contents into one byte array
+                                               for (int i=0; i<ARRLENGTH; i++) {
+                                                       heights[i] = inStream.read()*256 + inStream.read();
+                                                       if (heights[i] >= 32768) {heights[i] -= 65536;}
+                                               }
+                                       }
+                                       //else {
+                                       //      System.out.println("length not ok: " + entry.getSize());
+                                       //}
+                                       // Close stream from url
+                                       inStream.close();
+
+                                       if (entryOk)
+                                       {
+                                               // 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() || point.getAltitude().getValue() == 0) {
+                                                               if (new SrtmTile(point).equals(tile))
+                                                               {
+                                                                       double x = (point.getLongitude().getDouble() - tile.getLongitude()) * 1200;
+                                                                       double y = 1201 - (point.getLatitude().getDouble() - tile.getLatitude()) * 1200;
+                                                                       int idx1 = ((int)y)*1201 + (int)x;
+                                                                       try {
+                                                                               int[] fouralts = {heights[idx1], heights[idx1+1], heights[idx1-1201], heights[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;
+                                                                               }
+                                                                               if (altitude != VOID_VAL) {
+                                                                                       point.setFieldValue(Field.ALTITUDE, ""+altitude, false);
+                                                                                       numAltitudesFound++;
+                                                                               }
+                                                                       }
+                                                                       catch (ArrayIndexOutOfBoundsException obe) {
+                                                                               //System.err.println("lat=" + point.getLatitude().getDouble() + ", x=" + x + ", y=" + y + ", idx=" + idx1);
+                                                                       }
+                                                               }
+                                                       }
+                                               }
+                                       }
+                               }
+                               catch (IOException ioe) {
+                                       //System.err.println("eek - " + ioe.getMessage());
+                               }
+                       }
+               }
+               _dialog.dispose();
+               if (numAltitudesFound > 0)
+               {
+                       // Inform app including undo information
+                       track.requestRescale();
+                       UpdateMessageBroker.informSubscribers(DataSubscriber.DATA_ADDED_OR_REMOVED);
+                       _app.completeFunction(undo, I18nManager.getText("confirm.lookupsrtm1") + " " + numAltitudesFound
+                               + " " + I18nManager.getText("confirm.lookupsrtm2"));
+               }
+               else {
+                       _app.showErrorMessage(getNameKey(), "error.lookupsrtm.none");
+               }
+       }
+
+       /**
+        * Perform a bilinear interpolation on the given altitude array
+        * @param inAltitudes array of four altitude values on corners of square (bl, br, tl, tr)
+        * @param inX x coordinate
+        * @param inY y coordinate
+        * @return interpolated altitude
+        */
+       private static double bilinearInterpolate(int[] inAltitudes, double inX, double inY)
+       {
+               double alpha = inX - (int) inX;
+               double beta  = 1 - (inY - (int) inY);
+               double alt = (1-alpha)*(1-beta)*inAltitudes[0] + alpha*(1-beta)*inAltitudes[1]
+                       + (1-alpha)*beta*inAltitudes[2] + alpha*beta*inAltitudes[3];
+               return alt;
+       }
+
+       /**
+        * Fix a single void in the given array by replacing it with the average of the others
+        * @param inAltitudes array of altitudes containing one void
+        * @return fixed array without voids
+        */
+       private static int[] fixVoid(int[] inAltitudes)
+       {
+               int[] fixed = new int[inAltitudes.length];
+               for (int i=0; i<inAltitudes.length; i++) {
+                       if (inAltitudes[i] == VOID_VAL) {
+                               fixed[i] = (int) Math.round(averageNonVoid(inAltitudes));
+                       }
+                       else {
+                               fixed[i] = inAltitudes[i];
+                       }
+               }
+               return fixed;
+       }
+
+       /**
+        * Calculate the average of the non-void altitudes in the given array
+        * @param inAltitudes array of altitudes with one or more voids
+        * @return average of non-void altitudes
+        */
+       private static final double averageNonVoid(int[] inAltitudes)
+       {
+               double totalAltitude = 0.0;
+               int numAlts = 0;
+               for (int i=0; i<inAltitudes.length; i++) {
+                       if (inAltitudes[i] != VOID_VAL) {
+                               totalAltitude += inAltitudes[i];
+                               numAlts++;
+                       }
+               }
+               if (numAlts < 1) {return VOID_VAL;}
+               return totalAltitude / numAlts;
+       }
+}
diff --git a/tim/prune/function/srtm/SrtmTile.java b/tim/prune/function/srtm/SrtmTile.java
new file mode 100644 (file)
index 0000000..d7ab38f
--- /dev/null
@@ -0,0 +1,62 @@
+package tim.prune.function.srtm;
+
+import tim.prune.data.Coordinate;
+import tim.prune.data.DataPoint;
+
+/**
+ * Class to represent a single tile of Srtm data, from a single hgt.zip file
+ */
+public class SrtmTile
+{
+       /** Latitude in degrees north/south */
+       private int _latitude = 0;
+       /** Longitude ini degrees east/west */
+       private int _longitude = 0;
+
+       /**
+        * Constructor working out the tile for a single point
+        * @param inPoint data point
+        */
+       public SrtmTile(DataPoint inPoint)
+       {
+               Coordinate latitude = inPoint.getLatitude();
+               _latitude = (int) Math.floor(latitude.getDouble());
+               Coordinate longitude = inPoint.getLongitude();
+               _longitude = (int) Math.floor(longitude.getDouble());
+       }
+
+       /**
+        * Check for equality
+        * @param inOther other tile object
+        * @return true if both represent same tile
+        */
+       public boolean equals(SrtmTile inOther)
+       {
+               return (_latitude == inOther._latitude) && (_longitude == inOther._longitude);
+       }
+
+       /** @return latitude as int */
+       public int getLatitude() {
+               return _latitude;
+       }
+
+       /** @return longitude as int */
+       public int getLongitude() {
+               return _longitude;
+       }
+
+       /**
+        * @return filename of tile
+        */
+       public String getTileName()
+       {
+               return (_latitude >= 0?"N":"S")
+                       + (Math.abs(_latitude) < 10?"0":"")
+                       + Math.abs(_latitude)
+                       + (_longitude >= 0?"E":"W")
+                       + (Math.abs(_longitude) < 100?"0":"")
+                       + (Math.abs(_longitude) < 10?"0":"")
+                       + Math.abs(_longitude)
+                       + ".hgt.zip";
+       }
+}
diff --git a/tim/prune/function/srtm/TileFinder.java b/tim/prune/function/srtm/TileFinder.java
new file mode 100644 (file)
index 0000000..209db7f
--- /dev/null
@@ -0,0 +1,74 @@
+package tim.prune.function.srtm;
+
+import java.io.InputStream;
+import java.net.MalformedURLException;
+import java.net.URL;
+import java.util.ArrayList;
+
+
+/**
+ * Class to get the URLs of the SRTM tiles
+ * using the srtmtiles.dat file
+ */
+public abstract class TileFinder
+{
+       /** URL prefix for all tiles */
+       private static final String URL_PREFIX = "http://dds.cr.usgs.gov/srtm/version2_1/SRTM3/";
+       /** Directory names for each continent */
+       private static final String[] CONTINENTS = {"", "Eurasia", "North_America", "Australia",
+               "Islands", "South_America", "Africa"};
+
+
+       /**
+        * Get the Urls for the given list of tiles
+        * @param inTiles list of Tiles to get
+        * @return array of URLs
+        */
+       public static URL[] getUrls(ArrayList<SrtmTile> inTiles)
+       {
+               if (inTiles == null || inTiles.size() < 1) {return null;}
+               URL[] urls = new URL[inTiles.size()];
+               // Read dat file into array
+               byte[] lookup = readDatFile();
+               for (int t=0; t<inTiles.size(); t++)
+               {
+                       SrtmTile tile = inTiles.get(t);
+                       // Get byte from lookup array
+                       int idx = (tile.getLatitude() + 59)*360 + (tile.getLongitude() + 180);
+                       try
+                       {
+                               int dir = lookup[idx];
+                               if (dir > 0) {
+                                       try {
+                                               urls[t] = new URL(URL_PREFIX + CONTINENTS[dir] + "/" + tile.getTileName());
+                                       } catch (MalformedURLException e) {} // ignore error, url stays null
+                               }
+                       } catch (ArrayIndexOutOfBoundsException e) {} // ignore error, url stays null
+               }
+               return urls;
+       }
+
+       /**
+        * Read the dat file and get the contents
+        * @return byte array containing file contents
+        */
+       private static byte[] readDatFile()
+       {
+               try
+               {
+                       // Need absolute path to dat file
+                       InputStream in = TileFinder.class.getResourceAsStream("/tim/prune/function/srtm/srtmtiles.dat");
+                       if (in != null)
+                       {
+                               byte[] buffer = new byte[in.available()];
+                               in.read(buffer);
+                               in.close();
+                               return buffer;
+                       }
+               }
+               catch (java.io.IOException e) {
+                       System.err.println("Exception trying to read srtmtiles.dat : " + e.getMessage());
+               }
+               return null;
+       }
+}
diff --git a/tim/prune/function/srtm/gen/GenerateTileLookup.java b/tim/prune/function/srtm/gen/GenerateTileLookup.java
new file mode 100644 (file)
index 0000000..d797b13
--- /dev/null
@@ -0,0 +1,70 @@
+package tim.prune.function.srtm.gen;
+
+import java.io.BufferedReader;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.FileReader;
+
+/**
+ * Class used to generate a lookup file to find the URLs of SRTM tiles.
+ * The tiles are split into directories for each continent, so we need some way
+ * of going from coordinates to directories.
+ * This class reads the directory listings from the files tiles1.txt, tiles2.txt etc
+ * and combines the result into a binary array
+ */
+public class GenerateTileLookup
+{
+
+       /**
+        * Main method for generating the array
+        * @param args ignored
+        */
+       public static void main(String[] args)
+       {
+               System.out.println("Generate tile lookup");
+               byte[] lookup = new byte[360 * 120]; // +/- 180 degrees longitude, +/- 60 degrees latitude
+               for (int f=1; f<= 6; f++)
+               {
+                       try
+                       {
+                               BufferedReader r = new BufferedReader(new FileReader(new File("tim/prune/function/srtm/gen/tiles" + f + ".txt")));
+                               String line = r.readLine();
+                               System.out.println("Read continent: '" + line + "'");
+                               while ((line = r.readLine()) != null) {
+                                       if (line.length() == 7)
+                                       {
+                                               boolean north = (line.charAt(0) == 'N');
+                                               int lat = Integer.parseInt(line.substring(1, 3));
+                                               if (!north) {lat = -lat;}
+                                               boolean east = (line.charAt(3) == 'E');
+                                               int lon = Integer.parseInt(line.substring(4));
+                                               if (!east) {lon = -lon;}
+                                               // Store in lookup
+                                               int arrindex = (lat+59)*360 + (lon+180);
+                                               lookup[arrindex] = (byte) f;
+                                       }
+                               }
+                       }
+                       catch (Exception e) {
+                               e.printStackTrace();
+                       }
+               }
+               // Now f should be populated
+               StringBuilder b = new StringBuilder();
+               for (int l=-180; l<180; l++) {
+                       int i = 59 * 360 + (l+180);
+                       b.append("" + lookup[i]);
+               }
+               System.out.println("equator: " + b.toString());
+
+               // Write bytes to file
+               try {
+                       FileOutputStream out = new FileOutputStream(new File("srtmtiles.dat"));
+                       out.write(lookup);
+                       out.close();
+               }
+               catch (Exception e) {
+                       e.printStackTrace();
+               }
+       }
+}
diff --git a/tim/prune/function/srtm/gen/tiles1.txt b/tim/prune/function/srtm/gen/tiles1.txt
new file mode 100644 (file)
index 0000000..9b88f20
--- /dev/null
@@ -0,0 +1,5878 @@
+Eurasia
+N00E072
+N00E073
+N00E097
+N00E098
+N00E099
+N00E100
+N00E101
+N00E102
+N00E103
+N00E104
+N00E106
+N00E107
+N00E108
+N00E109
+N00E110
+N00E111
+N00E112
+N00E113
+N00E114
+N00E115
+N00E116
+N00E117
+N00E118
+N00E119
+N00E120
+N00E121
+N00E122
+N00E123
+N00E124
+N00E126
+N00E127
+N00E128
+N00E129
+N00E130
+N00E131
+N00E134
+N00E172
+N00E173
+N00W177
+N01E073
+N01E097
+N01E098
+N01E099
+N01E100
+N01E101
+N01E102
+N01E103
+N01E104
+N01E106
+N01E107
+N01E108
+N01E109
+N01E110
+N01E111
+N01E112
+N01E113
+N01E114
+N01E115
+N01E116
+N01E117
+N01E118
+N01E119
+N01E120
+N01E121
+N01E122
+N01E124
+N01E125
+N01E126
+N01E127
+N01E128
+N01E131
+N01E154
+N01E172
+N01E173
+N01W158
+N02E072
+N02E073
+N02E095
+N02E096
+N02E097
+N02E098
+N02E099
+N02E100
+N02E101
+N02E102
+N02E103
+N02E104
+N02E105
+N02E106
+N02E107
+N02E108
+N02E109
+N02E111
+N02E112
+N02E113
+N02E114
+N02E115
+N02E116
+N02E117
+N02E118
+N02E125
+N02E127
+N02E128
+N02E131
+N02E173
+N02W158
+N03E072
+N03E073
+N03E095
+N03E096
+N03E097
+N03E098
+N03E099
+N03E100
+N03E101
+N03E102
+N03E103
+N03E105
+N03E106
+N03E107
+N03E108
+N03E112
+N03E113
+N03E114
+N03E115
+N03E116
+N03E117
+N03E125
+N03E126
+N03E131
+N03E154
+N03E172
+N03E173
+N03W160
+N04E072
+N04E073
+N04E095
+N04E096
+N04E097
+N04E098
+N04E100
+N04E101
+N04E102
+N04E103
+N04E107
+N04E108
+N04E113
+N04E114
+N04E115
+N04E116
+N04E117
+N04E118
+N04E119
+N04E125
+N04E126
+N04E127
+N04E131
+N04E132
+N04E168
+N04W161
+N05E072
+N05E073
+N05E080
+N05E094
+N05E095
+N05E096
+N05E097
+N05E100
+N05E101
+N05E102
+N05E103
+N05E114
+N05E115
+N05E116
+N05E117
+N05E118
+N05E119
+N05E120
+N05E121
+N05E124
+N05E125
+N05E126
+N05E132
+N05E153
+N05E157
+N05E162
+N05E163
+N05E168
+N05E169
+N05E172
+N05W163
+N06E072
+N06E073
+N06E079
+N06E080
+N06E081
+N06E093
+N06E095
+N06E099
+N06E100
+N06E101
+N06E102
+N06E115
+N06E116
+N06E117
+N06E118
+N06E120
+N06E121
+N06E122
+N06E123
+N06E124
+N06E125
+N06E126
+N06E134
+N06E143
+N06E149
+N06E151
+N06E152
+N06E157
+N06E158
+N06E159
+N06E160
+N06E169
+N06E171
+N06E172
+N06W163
+N07E072
+N07E073
+N07E079
+N07E080
+N07E081
+N07E093
+N07E098
+N07E099
+N07E100
+N07E113
+N07E116
+N07E117
+N07E118
+N07E121
+N07E122
+N07E123
+N07E124
+N07E125
+N07E126
+N07E134
+N07E143
+N07E144
+N07E145
+N07E146
+N07E147
+N07E149
+N07E151
+N07E152
+N07E155
+N07E157
+N07E158
+N07E168
+N07E171
+N08E073
+N08E076
+N08E077
+N08E078
+N08E079
+N08E080
+N08E081
+N08E092
+N08E093
+N08E097
+N08E098
+N08E099
+N08E100
+N08E104
+N08E105
+N08E106
+N08E111
+N08E116
+N08E117
+N08E118
+N08E122
+N08E123
+N08E124
+N08E125
+N08E126
+N08E134
+N08E137
+N08E140
+N08E144
+N08E146
+N08E147
+N08E149
+N08E150
+N08E151
+N08E152
+N08E154
+N08E165
+N08E166
+N08E167
+N08E168
+N08E170
+N08E171
+N09E076
+N09E077
+N09E078
+N09E079
+N09E080
+N09E092
+N09E097
+N09E098
+N09E099
+N09E100
+N09E102
+N09E103
+N09E104
+N09E105
+N09E106
+N09E109
+N09E117
+N09E118
+N09E119
+N09E120
+N09E121
+N09E122
+N09E123
+N09E124
+N09E125
+N09E126
+N09E138
+N09E139
+N09E140
+N09E145
+N09E160
+N09E165
+N09E166
+N09E167
+N09E169
+N09E170
+N10E072
+N10E073
+N10E075
+N10E076
+N10E077
+N10E078
+N10E079
+N10E092
+N10E097
+N10E098
+N10E099
+N10E102
+N10E103
+N10E104
+N10E105
+N10E106
+N10E107
+N10E108
+N10E114
+N10E115
+N10E118
+N10E119
+N10E120
+N10E121
+N10E122
+N10E123
+N10E124
+N10E125
+N10E126
+N10E139
+N10E165
+N10E166
+N10E168
+N10E169
+N10E170
+N11E072
+N11E073
+N11E075
+N11E076
+N11E077
+N11E078
+N11E079
+N11E092
+N11E093
+N11E097
+N11E098
+N11E099
+N11E102
+N11E103
+N11E104
+N11E105
+N11E106
+N11E107
+N11E108
+N11E109
+N11E114
+N11E115
+N11E119
+N11E120
+N11E121
+N11E122
+N11E123
+N11E124
+N11E125
+N11E162
+N11E165
+N11E166
+N11E167
+N11E169
+N12E074
+N12E075
+N12E076
+N12E077
+N12E078
+N12E079
+N12E080
+N12E092
+N12E093
+N12E097
+N12E098
+N12E099
+N12E100
+N12E101
+N12E102
+N12E103
+N12E104
+N12E105
+N12E106
+N12E107
+N12E108
+N12E109
+N12E119
+N12E120
+N12E121
+N12E122
+N12E123
+N12E124
+N12E125
+N12E170
+N13E074
+N13E075
+N13E076
+N13E077
+N13E078
+N13E079
+N13E080
+N13E092
+N13E093
+N13E094
+N13E097
+N13E098
+N13E099
+N13E100
+N13E101
+N13E102
+N13E103
+N13E104
+N13E105
+N13E106
+N13E107
+N13E108
+N13E109
+N13E120
+N13E121
+N13E122
+N13E123
+N13E124
+N13E144
+N14E074
+N14E075
+N14E076
+N14E077
+N14E078
+N14E079
+N14E080
+N14E093
+N14E097
+N14E098
+N14E099
+N14E100
+N14E101
+N14E102
+N14E103
+N14E104
+N14E105
+N14E106
+N14E107
+N14E108
+N14E109
+N14E120
+N14E121
+N14E122
+N14E123
+N14E124
+N14E145
+N14E168
+N14E169
+N15E073
+N15E074
+N15E075
+N15E076
+N15E077
+N15E078
+N15E079
+N15E080
+N15E081
+N15E094
+N15E095
+N15E097
+N15E098
+N15E099
+N15E100
+N15E101
+N15E102
+N15E103
+N15E104
+N15E105
+N15E106
+N15E107
+N15E108
+N15E109
+N15E111
+N15E119
+N15E120
+N15E121
+N15E122
+N15E145
+N16E073
+N16E074
+N16E075
+N16E076
+N16E077
+N16E078
+N16E079
+N16E080
+N16E081
+N16E082
+N16E094
+N16E095
+N16E096
+N16E097
+N16E098
+N16E099
+N16E100
+N16E101
+N16E102
+N16E103
+N16E104
+N16E105
+N16E106
+N16E107
+N16E108
+N16E111
+N16E112
+N16E119
+N16E120
+N16E121
+N16E122
+N16E145
+N16E146
+N17E073
+N17E074
+N17E075
+N17E076
+N17E077
+N17E078
+N17E079
+N17E080
+N17E081
+N17E082
+N17E083
+N17E094
+N17E095
+N17E096
+N17E097
+N17E098
+N17E099
+N17E100
+N17E101
+N17E102
+N17E103
+N17E104
+N17E105
+N17E106
+N17E107
+N17E120
+N17E121
+N17E122
+N17E145
+N18E072
+N18E073
+N18E074
+N18E075
+N18E076
+N18E077
+N18E078
+N18E079
+N18E080
+N18E081
+N18E082
+N18E083
+N18E084
+N18E093
+N18E094
+N18E095
+N18E096
+N18E097
+N18E098
+N18E099
+N18E100
+N18E101
+N18E102
+N18E103
+N18E104
+N18E105
+N18E106
+N18E108
+N18E109
+N18E110
+N18E120
+N18E121
+N18E122
+N18E145
+N19E072
+N19E073
+N19E074
+N19E075
+N19E076
+N19E077
+N19E078
+N19E079
+N19E080
+N19E081
+N19E082
+N19E083
+N19E084
+N19E085
+N19E086
+N19E092
+N19E093
+N19E094
+N19E095
+N19E096
+N19E097
+N19E098
+N19E099
+N19E100
+N19E101
+N19E102
+N19E103
+N19E104
+N19E105
+N19E106
+N19E108
+N19E109
+N19E110
+N19E111
+N19E121
+N19E122
+N19E145
+N19E166
+N20E070
+N20E071
+N20E072
+N20E073
+N20E074
+N20E075
+N20E076
+N20E077
+N20E078
+N20E079
+N20E080
+N20E081
+N20E082
+N20E083
+N20E084
+N20E085
+N20E086
+N20E087
+N20E092
+N20E093
+N20E094
+N20E095
+N20E096
+N20E097
+N20E098
+N20E099
+N20E100
+N20E101
+N20E102
+N20E103
+N20E104
+N20E105
+N20E106
+N20E107
+N20E109
+N20E110
+N20E116
+N20E121
+N20E122
+N20E136
+N20E144
+N20E145
+N21E069
+N21E070
+N21E071
+N21E072
+N21E073
+N21E074
+N21E075
+N21E076
+N21E077
+N21E078
+N21E079
+N21E080
+N21E081
+N21E082
+N21E083
+N21E084
+N21E085
+N21E086
+N21E087
+N21E088
+N21E089
+N21E090
+N21E091
+N21E092
+N21E093
+N21E094
+N21E095
+N21E096
+N21E097
+N21E098
+N21E099
+N21E100
+N21E101
+N21E102
+N21E103
+N21E104
+N21E105
+N21E106
+N21E107
+N21E108
+N21E109
+N21E110
+N21E111
+N21E112
+N21E113
+N21E114
+N21E120
+N21E121
+N22E068
+N22E069
+N22E070
+N22E071
+N22E072
+N22E073
+N22E074
+N22E075
+N22E076
+N22E077
+N22E078
+N22E079
+N22E080
+N22E081
+N22E082
+N22E083
+N22E084
+N22E085
+N22E086
+N22E087
+N22E088
+N22E089
+N22E090
+N22E091
+N22E092
+N22E093
+N22E094
+N22E095
+N22E096
+N22E097
+N22E098
+N22E099
+N22E100
+N22E101
+N22E102
+N22E103
+N22E104
+N22E105
+N22E106
+N22E107
+N22E108
+N22E109
+N22E110
+N22E111
+N22E112
+N22E113
+N22E114
+N22E115
+N22E116
+N22E120
+N22E121
+N23E067
+N23E068
+N23E069
+N23E070
+N23E071
+N23E072
+N23E073
+N23E074
+N23E075
+N23E076
+N23E077
+N23E078
+N23E079
+N23E080
+N23E081
+N23E082
+N23E083
+N23E084
+N23E085
+N23E086
+N23E087
+N23E088
+N23E089
+N23E090
+N23E091
+N23E092
+N23E093
+N23E094
+N23E095
+N23E096
+N23E097
+N23E098
+N23E099
+N23E100
+N23E101
+N23E102
+N23E103
+N23E104
+N23E105
+N23E106
+N23E107
+N23E108
+N23E109
+N23E110
+N23E111
+N23E112
+N23E113
+N23E114
+N23E115
+N23E116
+N23E117
+N23E119
+N23E120
+N23E121
+N24E066
+N24E067
+N24E068
+N24E069
+N24E070
+N24E071
+N24E072
+N24E073
+N24E074
+N24E075
+N24E076
+N24E077
+N24E078
+N24E079
+N24E080
+N24E081
+N24E082
+N24E083
+N24E084
+N24E085
+N24E086
+N24E087
+N24E088
+N24E089
+N24E090
+N24E091
+N24E092
+N24E093
+N24E094
+N24E095
+N24E096
+N24E097
+N24E098
+N24E099
+N24E100
+N24E101
+N24E102
+N24E103
+N24E104
+N24E105
+N24E106
+N24E107
+N24E108
+N24E109
+N24E110
+N24E111
+N24E112
+N24E113
+N24E114
+N24E115
+N24E116
+N24E117
+N24E118
+N24E119
+N24E120
+N24E121
+N24E122
+N24E123
+N24E124
+N24E125
+N24E131
+N24E141
+N24E153
+N25E060
+N25E061
+N25E062
+N25E063
+N25E064
+N25E065
+N25E066
+N25E067
+N25E068
+N25E069
+N25E070
+N25E071
+N25E072
+N25E073
+N25E074
+N25E075
+N25E076
+N25E077
+N25E078
+N25E079
+N25E080
+N25E081
+N25E082
+N25E083
+N25E084
+N25E085
+N25E086
+N25E087
+N25E088
+N25E089
+N25E090
+N25E091
+N25E092
+N25E093
+N25E094
+N25E095
+N25E096
+N25E097
+N25E098
+N25E099
+N25E100
+N25E101
+N25E102
+N25E103
+N25E104
+N25E105
+N25E106
+N25E107
+N25E108
+N25E109
+N25E110
+N25E111
+N25E112
+N25E113
+N25E114
+N25E115
+N25E116
+N25E117
+N25E118
+N25E119
+N25E121
+N25E122
+N25E123
+N25E124
+N25E131
+N25E141
+N26E060
+N26E061
+N26E062
+N26E063
+N26E064
+N26E065
+N26E066
+N26E067
+N26E068
+N26E069
+N26E070
+N26E071
+N26E072
+N26E073
+N26E074
+N26E075
+N26E076
+N26E077
+N26E078
+N26E079
+N26E080
+N26E081
+N26E082
+N26E083
+N26E084
+N26E085
+N26E086
+N26E087
+N26E088
+N26E089
+N26E090
+N26E091
+N26E092
+N26E093
+N26E094
+N26E095
+N26E096
+N26E097
+N26E098
+N26E099
+N26E100
+N26E101
+N26E102
+N26E103
+N26E104
+N26E105
+N26E106
+N26E107
+N26E108
+N26E109
+N26E110
+N26E111
+N26E112
+N26E113
+N26E114
+N26E115
+N26E116
+N26E117
+N26E118
+N26E119
+N26E120
+N26E126
+N26E127
+N26E128
+N26E142
+N27E060
+N27E061
+N27E062
+N27E063
+N27E064
+N27E065
+N27E066
+N27E067
+N27E068
+N27E069
+N27E070
+N27E071
+N27E072
+N27E073
+N27E074
+N27E075
+N27E076
+N27E077
+N27E078
+N27E079
+N27E080
+N27E081
+N27E082
+N27E083
+N27E084
+N27E085
+N27E086
+N27E087
+N27E088
+N27E089
+N27E090
+N27E091
+N27E092
+N27E093
+N27E094
+N27E095
+N27E096
+N27E097
+N27E098
+N27E099
+N27E100
+N27E101
+N27E102
+N27E103
+N27E104
+N27E105
+N27E106
+N27E107
+N27E108
+N27E109
+N27E110
+N27E111
+N27E112
+N27E113
+N27E114
+N27E115
+N27E116
+N27E117
+N27E118
+N27E119
+N27E120
+N27E121
+N27E127
+N27E128
+N27E129
+N27E140
+N27E142
+N28E060
+N28E061
+N28E062
+N28E063
+N28E064
+N28E065
+N28E066
+N28E067
+N28E068
+N28E069
+N28E070
+N28E071
+N28E072
+N28E073
+N28E074
+N28E075
+N28E076
+N28E077
+N28E078
+N28E079
+N28E080
+N28E081
+N28E082
+N28E083
+N28E084
+N28E085
+N28E086
+N28E087
+N28E088
+N28E089
+N28E090
+N28E091
+N28E092
+N28E093
+N28E094
+N28E095
+N28E096
+N28E097
+N28E098
+N28E099
+N28E100
+N28E101
+N28E102
+N28E103
+N28E104
+N28E105
+N28E106
+N28E107
+N28E108
+N28E109
+N28E110
+N28E111
+N28E112
+N28E113
+N28E114
+N28E115
+N28E116
+N28E117
+N28E118
+N28E119
+N28E120
+N28E121
+N28E122
+N28E128
+N28E129
+N28E130
+N29E060
+N29E061
+N29E062
+N29E063
+N29E064
+N29E065
+N29E066
+N29E067
+N29E068
+N29E069
+N29E070
+N29E071
+N29E072
+N29E073
+N29E074
+N29E075
+N29E076
+N29E077
+N29E078
+N29E079
+N29E080
+N29E081
+N29E082
+N29E083
+N29E084
+N29E085
+N29E086
+N29E087
+N29E088
+N29E089
+N29E090
+N29E091
+N29E092
+N29E093
+N29E094
+N29E095
+N29E096
+N29E097
+N29E098
+N29E099
+N29E100
+N29E101
+N29E102
+N29E103
+N29E104
+N29E105
+N29E106
+N29E107
+N29E108
+N29E109
+N29E110
+N29E111
+N29E112
+N29E113
+N29E114
+N29E115
+N29E116
+N29E117
+N29E118
+N29E119
+N29E120
+N29E121
+N29E122
+N29E129
+N29E140
+N30E060
+N30E061
+N30E062
+N30E063
+N30E064
+N30E065
+N30E066
+N30E067
+N30E068
+N30E069
+N30E070
+N30E071
+N30E072
+N30E073
+N30E074
+N30E075
+N30E076
+N30E077
+N30E078
+N30E079
+N30E080
+N30E081
+N30E082
+N30E083
+N30E084
+N30E085
+N30E086
+N30E087
+N30E088
+N30E089
+N30E090
+N30E091
+N30E092
+N30E093
+N30E094
+N30E095
+N30E096
+N30E097
+N30E098
+N30E099
+N30E100
+N30E101
+N30E102
+N30E103
+N30E104
+N30E105
+N30E106
+N30E107
+N30E108
+N30E109
+N30E110
+N30E111
+N30E112
+N30E113
+N30E114
+N30E115
+N30E116
+N30E117
+N30E118
+N30E119
+N30E120
+N30E121
+N30E122
+N30E129
+N30E130
+N30E131
+N30E140
+N31E060
+N31E061
+N31E062
+N31E063
+N31E064
+N31E065
+N31E066
+N31E067
+N31E068
+N31E069
+N31E070
+N31E071
+N31E072
+N31E073
+N31E074
+N31E075
+N31E076
+N31E077
+N31E078
+N31E079
+N31E080
+N31E081
+N31E082
+N31E083
+N31E084
+N31E085
+N31E086
+N31E087
+N31E088
+N31E089
+N31E090
+N31E091
+N31E092
+N31E093
+N31E094
+N31E095
+N31E096
+N31E097
+N31E098
+N31E099
+N31E100
+N31E101
+N31E102
+N31E103
+N31E104
+N31E105
+N31E106
+N31E107
+N31E108
+N31E109
+N31E110
+N31E111
+N31E112
+N31E113
+N31E114
+N31E115
+N31E116
+N31E117
+N31E118
+N31E119
+N31E120
+N31E121
+N31E122
+N31E128
+N31E129
+N31E130
+N31E131
+N31E139
+N31E140
+N32E060
+N32E061
+N32E062
+N32E063
+N32E064
+N32E065
+N32E066
+N32E067
+N32E068
+N32E069
+N32E070
+N32E071
+N32E072
+N32E073
+N32E074
+N32E075
+N32E076
+N32E077
+N32E078
+N32E079
+N32E080
+N32E081
+N32E082
+N32E083
+N32E084
+N32E085
+N32E086
+N32E087
+N32E088
+N32E089
+N32E090
+N32E091
+N32E092
+N32E093
+N32E094
+N32E095
+N32E096
+N32E097
+N32E098
+N32E099
+N32E100
+N32E101
+N32E102
+N32E103
+N32E104
+N32E105
+N32E106
+N32E107
+N32E108
+N32E109
+N32E110
+N32E111
+N32E112
+N32E113
+N32E114
+N32E115
+N32E116
+N32E117
+N32E118
+N32E119
+N32E120
+N32E121
+N32E128
+N32E129
+N32E130
+N32E131
+N32E132
+N32E133
+N32E139
+N33E060
+N33E061
+N33E062
+N33E063
+N33E064
+N33E065
+N33E066
+N33E067
+N33E068
+N33E069
+N33E070
+N33E071
+N33E072
+N33E073
+N33E074
+N33E075
+N33E076
+N33E077
+N33E078
+N33E079
+N33E080
+N33E081
+N33E082
+N33E083
+N33E084
+N33E085
+N33E086
+N33E087
+N33E088
+N33E089
+N33E090
+N33E091
+N33E092
+N33E093
+N33E094
+N33E095
+N33E096
+N33E097
+N33E098
+N33E099
+N33E100
+N33E101
+N33E102
+N33E103
+N33E104
+N33E105
+N33E106
+N33E107
+N33E108
+N33E109
+N33E110
+N33E111
+N33E112
+N33E113
+N33E114
+N33E115
+N33E116
+N33E117
+N33E118
+N33E119
+N33E120
+N33E126
+N33E128
+N33E129
+N33E130
+N33E131
+N33E132
+N33E133
+N33E134
+N33E135
+N33E136
+N33E138
+N33E139
+N34E060
+N34E061
+N34E062
+N34E063
+N34E064
+N34E065
+N34E066
+N34E067
+N34E068
+N34E069
+N34E070
+N34E071
+N34E072
+N34E073
+N34E074
+N34E075
+N34E076
+N34E077
+N34E078
+N34E079
+N34E080
+N34E081
+N34E082
+N34E083
+N34E084
+N34E085
+N34E086
+N34E087
+N34E088
+N34E089
+N34E090
+N34E091
+N34E092
+N34E093
+N34E094
+N34E095
+N34E096
+N34E097
+N34E098
+N34E099
+N34E100
+N34E101
+N34E102
+N34E103
+N34E104
+N34E105
+N34E106
+N34E107
+N34E108
+N34E109
+N34E110
+N34E111
+N34E112
+N34E113
+N34E114
+N34E115
+N34E116
+N34E117
+N34E118
+N34E119
+N34E120
+N34E125
+N34E126
+N34E127
+N34E128
+N34E129
+N34E130
+N34E131
+N34E132
+N34E133
+N34E134
+N34E135
+N34E136
+N34E137
+N34E138
+N34E139
+N35E000
+N35E001
+N35E002
+N35E003
+N35E004
+N35E005
+N35E006
+N35E007
+N35E008
+N35E009
+N35E010
+N35E011
+N35E012
+N35E014
+N35E023
+N35E024
+N35E025
+N35E026
+N35E027
+N35E032
+N35E033
+N35E034
+N35E035
+N35E036
+N35E037
+N35E038
+N35E039
+N35E040
+N35E041
+N35E042
+N35E043
+N35E044
+N35E045
+N35E046
+N35E047
+N35E048
+N35E049
+N35E050
+N35E051
+N35E052
+N35E053
+N35E054
+N35E055
+N35E056
+N35E057
+N35E058
+N35E059
+N35E060
+N35E061
+N35E062
+N35E063
+N35E064
+N35E065
+N35E066
+N35E067
+N35E068
+N35E069
+N35E070
+N35E071
+N35E072
+N35E073
+N35E074
+N35E075
+N35E076
+N35E077
+N35E078
+N35E079
+N35E080
+N35E081
+N35E082
+N35E083
+N35E084
+N35E085
+N35E086
+N35E087
+N35E088
+N35E089
+N35E090
+N35E091
+N35E092
+N35E093
+N35E094
+N35E095
+N35E096
+N35E097
+N35E098
+N35E099
+N35E100
+N35E101
+N35E102
+N35E103
+N35E104
+N35E105
+N35E106
+N35E107
+N35E108
+N35E109
+N35E110
+N35E111
+N35E112
+N35E113
+N35E114
+N35E115
+N35E116
+N35E117
+N35E118
+N35E119
+N35E120
+N35E125
+N35E126
+N35E127
+N35E128
+N35E129
+N35E132
+N35E133
+N35E134
+N35E135
+N35E136
+N35E137
+N35E138
+N35E139
+N35E140
+N35W001
+N35W002
+N35W003
+N35W004
+N35W005
+N35W006
+N35W007
+N36E000
+N36E001
+N36E002
+N36E003
+N36E004
+N36E005
+N36E006
+N36E007
+N36E008
+N36E009
+N36E010
+N36E011
+N36E012
+N36E014
+N36E015
+N36E021
+N36E022
+N36E023
+N36E024
+N36E025
+N36E026
+N36E027
+N36E028
+N36E029
+N36E030
+N36E031
+N36E032
+N36E033
+N36E034
+N36E035
+N36E036
+N36E037
+N36E038
+N36E039
+N36E040
+N36E041
+N36E042
+N36E043
+N36E044
+N36E045
+N36E046
+N36E047
+N36E048
+N36E049
+N36E050
+N36E051
+N36E052
+N36E053
+N36E054
+N36E055
+N36E056
+N36E057
+N36E058
+N36E059
+N36E060
+N36E061
+N36E062
+N36E063
+N36E064
+N36E065
+N36E066
+N36E067
+N36E068
+N36E069
+N36E070
+N36E071
+N36E072
+N36E073
+N36E074
+N36E075
+N36E076
+N36E077
+N36E078
+N36E079
+N36E080
+N36E081
+N36E082
+N36E083
+N36E084
+N36E085
+N36E086
+N36E087
+N36E088
+N36E089
+N36E090
+N36E091
+N36E092
+N36E093
+N36E094
+N36E095
+N36E096
+N36E097
+N36E098
+N36E099
+N36E100
+N36E101
+N36E102
+N36E103
+N36E104
+N36E105
+N36E106
+N36E107
+N36E108
+N36E109
+N36E110
+N36E111
+N36E112
+N36E113
+N36E114
+N36E115
+N36E116
+N36E117
+N36E118
+N36E119
+N36E120
+N36E121
+N36E122
+N36E125
+N36E126
+N36E127
+N36E128
+N36E129
+N36E132
+N36E133
+N36E135
+N36E136
+N36E137
+N36E138
+N36E139
+N36E140
+N36W002
+N36W003
+N36W004
+N36W005
+N36W006
+N36W007
+N36W008
+N36W009
+N37E006
+N37E007
+N37E008
+N37E009
+N37E010
+N37E011
+N37E012
+N37E013
+N37E014
+N37E015
+N37E016
+N37E020
+N37E021
+N37E022
+N37E023
+N37E024
+N37E025
+N37E026
+N37E027
+N37E028
+N37E029
+N37E030
+N37E031
+N37E032
+N37E033
+N37E034
+N37E035
+N37E036
+N37E037
+N37E038
+N37E039
+N37E040
+N37E041
+N37E042
+N37E043
+N37E044
+N37E045
+N37E046
+N37E047
+N37E048
+N37E049
+N37E050
+N37E053
+N37E054
+N37E055
+N37E056
+N37E057
+N37E058
+N37E059
+N37E060
+N37E061
+N37E062
+N37E063
+N37E064
+N37E065
+N37E066
+N37E067
+N37E068
+N37E069
+N37E070
+N37E071
+N37E072
+N37E073
+N37E074
+N37E075
+N37E076
+N37E077
+N37E078
+N37E079
+N37E080
+N37E081
+N37E082
+N37E083
+N37E084
+N37E085
+N37E086
+N37E087
+N37E088
+N37E089
+N37E090
+N37E091
+N37E092
+N37E093
+N37E094
+N37E095
+N37E096
+N37E097
+N37E098
+N37E099
+N37E100
+N37E101
+N37E102
+N37E103
+N37E104
+N37E105
+N37E106
+N37E107
+N37E108
+N37E109
+N37E110
+N37E111
+N37E112
+N37E113
+N37E114
+N37E115
+N37E116
+N37E117
+N37E118
+N37E119
+N37E120
+N37E121
+N37E122
+N37E124
+N37E125
+N37E126
+N37E127
+N37E128
+N37E129
+N37E130
+N37E131
+N37E136
+N37E137
+N37E138
+N37E139
+N37E140
+N37E141
+N37W001
+N37W002
+N37W003
+N37W004
+N37W005
+N37W006
+N37W007
+N37W008
+N37W009
+N38E000
+N38E001
+N38E008
+N38E009
+N38E012
+N38E013
+N38E014
+N38E015
+N38E016
+N38E017
+N38E020
+N38E021
+N38E022
+N38E023
+N38E024
+N38E025
+N38E026
+N38E027
+N38E028
+N38E029
+N38E030
+N38E031
+N38E032
+N38E033
+N38E034
+N38E035
+N38E036
+N38E037
+N38E038
+N38E039
+N38E040
+N38E041
+N38E042
+N38E043
+N38E044
+N38E045
+N38E046
+N38E047
+N38E048
+N38E049
+N38E053
+N38E054
+N38E055
+N38E056
+N38E057
+N38E058
+N38E059
+N38E060
+N38E061
+N38E062
+N38E063
+N38E064
+N38E065
+N38E066
+N38E067
+N38E068
+N38E069
+N38E070
+N38E071
+N38E072
+N38E073
+N38E074
+N38E075
+N38E076
+N38E077
+N38E078
+N38E079
+N38E080
+N38E081
+N38E082
+N38E083
+N38E084
+N38E085
+N38E086
+N38E087
+N38E088
+N38E089
+N38E090
+N38E091
+N38E092
+N38E093
+N38E094
+N38E095
+N38E096
+N38E097
+N38E098
+N38E099
+N38E100
+N38E101
+N38E102
+N38E103
+N38E104
+N38E105
+N38E106
+N38E107
+N38E108
+N38E109
+N38E110
+N38E111
+N38E112
+N38E113
+N38E114
+N38E115
+N38E116
+N38E117
+N38E118
+N38E120
+N38E121
+N38E124
+N38E125
+N38E126
+N38E127
+N38E128
+N38E138
+N38E139
+N38E140
+N38E141
+N38W001
+N38W002
+N38W003
+N38W004
+N38W005
+N38W006
+N38W007
+N38W008
+N38W009
+N38W010
+N39E000
+N39E001
+N39E002
+N39E003
+N39E004
+N39E008
+N39E009
+N39E015
+N39E016
+N39E017
+N39E018
+N39E019
+N39E020
+N39E021
+N39E022
+N39E023
+N39E024
+N39E025
+N39E026
+N39E027
+N39E028
+N39E029
+N39E030
+N39E031
+N39E032
+N39E033
+N39E034
+N39E035
+N39E036
+N39E037
+N39E038
+N39E039
+N39E040
+N39E041
+N39E042
+N39E043
+N39E044
+N39E045
+N39E046
+N39E047
+N39E048
+N39E049
+N39E052
+N39E053
+N39E054
+N39E055
+N39E056
+N39E057
+N39E058
+N39E059
+N39E060
+N39E061
+N39E062
+N39E063
+N39E064
+N39E065
+N39E066
+N39E067
+N39E068
+N39E069
+N39E070
+N39E071
+N39E072
+N39E073
+N39E074
+N39E075
+N39E076
+N39E077
+N39E078
+N39E079
+N39E080
+N39E081
+N39E082
+N39E083
+N39E084
+N39E085
+N39E086
+N39E087
+N39E088
+N39E089
+N39E090
+N39E091
+N39E092
+N39E093
+N39E094
+N39E095
+N39E096
+N39E097
+N39E098
+N39E099
+N39E100
+N39E101
+N39E102
+N39E103
+N39E104
+N39E105
+N39E106
+N39E107
+N39E108
+N39E109
+N39E110
+N39E111
+N39E112
+N39E113
+N39E114
+N39E115
+N39E116
+N39E117
+N39E118
+N39E119
+N39E121
+N39E122
+N39E123
+N39E124
+N39E125
+N39E126
+N39E127
+N39E128
+N39E139
+N39E140
+N39E141
+N39E142
+N39W001
+N39W002
+N39W003
+N39W004
+N39W005
+N39W006
+N39W007
+N39W008
+N39W009
+N39W010
+N40E000
+N40E003
+N40E004
+N40E008
+N40E009
+N40E012
+N40E013
+N40E014
+N40E015
+N40E016
+N40E017
+N40E018
+N40E019
+N40E020
+N40E021
+N40E022
+N40E023
+N40E024
+N40E025
+N40E026
+N40E027
+N40E028
+N40E029
+N40E030
+N40E031
+N40E032
+N40E033
+N40E034
+N40E035
+N40E036
+N40E037
+N40E038
+N40E039
+N40E040
+N40E041
+N40E042
+N40E043
+N40E044
+N40E045
+N40E046
+N40E047
+N40E048
+N40E049
+N40E050
+N40E052
+N40E053
+N40E054
+N40E055
+N40E056
+N40E057
+N40E058
+N40E059
+N40E060
+N40E061
+N40E062
+N40E063
+N40E064
+N40E065
+N40E066
+N40E067
+N40E068
+N40E069
+N40E070
+N40E071
+N40E072
+N40E073
+N40E074
+N40E075
+N40E076
+N40E077
+N40E078
+N40E079
+N40E080
+N40E081
+N40E082
+N40E083
+N40E084
+N40E085
+N40E086
+N40E087
+N40E088
+N40E089
+N40E090
+N40E091
+N40E092
+N40E093
+N40E094
+N40E095
+N40E096
+N40E097
+N40E098
+N40E099
+N40E100
+N40E101
+N40E102
+N40E103
+N40E104
+N40E105
+N40E106
+N40E107
+N40E108
+N40E109
+N40E110
+N40E111
+N40E112
+N40E113
+N40E114
+N40E115
+N40E116
+N40E117
+N40E118
+N40E119
+N40E120
+N40E121
+N40E122
+N40E123
+N40E124
+N40E125
+N40E126
+N40E127
+N40E128
+N40E129
+N40E139
+N40E140
+N40E141
+N40W001
+N40W002
+N40W003
+N40W004
+N40W005
+N40W006
+N40W007
+N40W008
+N40W009
+N41E000
+N41E001
+N41E002
+N41E003
+N41E008
+N41E009
+N41E011
+N41E012
+N41E013
+N41E014
+N41E015
+N41E016
+N41E017
+N41E019
+N41E020
+N41E021
+N41E022
+N41E023
+N41E024
+N41E025
+N41E026
+N41E027
+N41E028
+N41E029
+N41E030
+N41E031
+N41E032
+N41E033
+N41E034
+N41E035
+N41E036
+N41E037
+N41E038
+N41E039
+N41E040
+N41E041
+N41E042
+N41E043
+N41E044
+N41E045
+N41E046
+N41E047
+N41E048
+N41E049
+N41E052
+N41E053
+N41E054
+N41E055
+N41E056
+N41E057
+N41E058
+N41E059
+N41E060
+N41E061
+N41E062
+N41E063
+N41E064
+N41E065
+N41E066
+N41E067
+N41E068
+N41E069
+N41E070
+N41E071
+N41E072
+N41E073
+N41E074
+N41E075
+N41E076
+N41E077
+N41E078
+N41E079
+N41E080
+N41E081
+N41E082
+N41E083
+N41E084
+N41E085
+N41E086
+N41E087
+N41E088
+N41E089
+N41E090
+N41E091
+N41E092
+N41E093
+N41E094
+N41E095
+N41E096
+N41E097
+N41E098
+N41E099
+N41E100
+N41E101
+N41E102
+N41E103
+N41E104
+N41E105
+N41E106
+N41E107
+N41E108
+N41E109
+N41E110
+N41E111
+N41E112
+N41E113
+N41E114
+N41E115
+N41E116
+N41E117
+N41E118
+N41E119
+N41E120
+N41E121
+N41E122
+N41E123
+N41E124
+N41E125
+N41E126
+N41E127
+N41E128
+N41E129
+N41E130
+N41E139
+N41E140
+N41E141
+N41E143
+N41W001
+N41W002
+N41W003
+N41W004
+N41W005
+N41W006
+N41W007
+N41W008
+N41W009
+N42E000
+N42E001
+N42E002
+N42E003
+N42E006
+N42E008
+N42E009
+N42E010
+N42E011
+N42E012
+N42E013
+N42E014
+N42E015
+N42E016
+N42E017
+N42E018
+N42E019
+N42E020
+N42E021
+N42E022
+N42E023
+N42E024
+N42E025
+N42E026
+N42E027
+N42E028
+N42E033
+N42E034
+N42E035
+N42E040
+N42E041
+N42E042
+N42E043
+N42E044
+N42E045
+N42E046
+N42E047
+N42E048
+N42E051
+N42E052
+N42E053
+N42E054
+N42E055
+N42E056
+N42E057
+N42E058
+N42E059
+N42E060
+N42E061
+N42E062
+N42E063
+N42E064
+N42E065
+N42E066
+N42E067
+N42E068
+N42E069
+N42E070
+N42E071
+N42E072
+N42E073
+N42E074
+N42E075
+N42E076
+N42E077
+N42E078
+N42E079
+N42E080
+N42E081
+N42E082
+N42E083
+N42E084
+N42E085
+N42E086
+N42E087
+N42E088
+N42E089
+N42E090
+N42E091
+N42E092
+N42E093
+N42E094
+N42E095
+N42E096
+N42E097
+N42E098
+N42E099
+N42E100
+N42E101
+N42E102
+N42E103
+N42E104
+N42E105
+N42E106
+N42E107
+N42E108
+N42E109
+N42E110
+N42E111
+N42E112
+N42E113
+N42E114
+N42E115
+N42E116
+N42E117
+N42E118
+N42E119
+N42E120
+N42E121
+N42E122
+N42E123
+N42E124
+N42E125
+N42E126
+N42E127
+N42E128
+N42E129
+N42E130
+N42E131
+N42E132
+N42E133
+N42E134
+N42E139
+N42E140
+N42E141
+N42E142
+N42E143
+N42E144
+N42E145
+N42W001
+N42W002
+N42W003
+N42W004
+N42W005
+N42W006
+N42W007
+N42W008
+N42W009
+N42W010
+N43E000
+N43E001
+N43E002
+N43E003
+N43E004
+N43E005
+N43E006
+N43E007
+N43E008
+N43E009
+N43E010
+N43E011
+N43E012
+N43E013
+N43E015
+N43E016
+N43E017
+N43E018
+N43E019
+N43E020
+N43E021
+N43E022
+N43E023
+N43E024
+N43E025
+N43E026
+N43E027
+N43E028
+N43E039
+N43E040
+N43E041
+N43E042
+N43E043
+N43E044
+N43E045
+N43E046
+N43E047
+N43E050
+N43E051
+N43E052
+N43E053
+N43E054
+N43E055
+N43E056
+N43E057
+N43E058
+N43E059
+N43E060
+N43E061
+N43E062
+N43E063
+N43E064
+N43E065
+N43E066
+N43E067
+N43E068
+N43E069
+N43E070
+N43E071
+N43E072
+N43E073
+N43E074
+N43E075
+N43E076
+N43E077
+N43E078
+N43E079
+N43E080
+N43E081
+N43E082
+N43E083
+N43E084
+N43E085
+N43E086
+N43E087
+N43E088
+N43E089
+N43E090
+N43E091
+N43E092
+N43E093
+N43E094
+N43E095
+N43E096
+N43E097
+N43E098
+N43E099
+N43E100
+N43E101
+N43E102
+N43E103
+N43E104
+N43E105
+N43E106
+N43E107
+N43E108
+N43E109
+N43E110
+N43E111
+N43E112
+N43E113
+N43E114
+N43E115
+N43E116
+N43E117
+N43E118
+N43E119
+N43E120
+N43E121
+N43E122
+N43E123
+N43E124
+N43E125
+N43E126
+N43E127
+N43E128
+N43E129
+N43E130
+N43E131
+N43E132
+N43E133
+N43E134
+N43E135
+N43E140
+N43E141
+N43E142
+N43E143
+N43E144
+N43E145
+N43E146
+N43W001
+N43W002
+N43W003
+N43W004
+N43W005
+N43W006
+N43W007
+N43W008
+N43W009
+N43W010
+N44E000
+N44E001
+N44E002
+N44E003
+N44E004
+N44E005
+N44E006
+N44E007
+N44E008
+N44E009
+N44E010
+N44E011
+N44E012
+N44E013
+N44E014
+N44E015
+N44E016
+N44E017
+N44E018
+N44E019
+N44E020
+N44E021
+N44E022
+N44E023
+N44E024
+N44E025
+N44E026
+N44E027
+N44E028
+N44E029
+N44E033
+N44E034
+N44E035
+N44E037
+N44E038
+N44E039
+N44E040
+N44E041
+N44E042
+N44E043
+N44E044
+N44E045
+N44E046
+N44E047
+N44E050
+N44E051
+N44E052
+N44E053
+N44E054
+N44E055
+N44E056
+N44E057
+N44E058
+N44E059
+N44E060
+N44E061
+N44E062
+N44E063
+N44E064
+N44E065
+N44E066
+N44E067
+N44E068
+N44E069
+N44E070
+N44E071
+N44E072
+N44E073
+N44E074
+N44E075
+N44E076
+N44E077
+N44E078
+N44E079
+N44E080
+N44E081
+N44E082
+N44E083
+N44E084
+N44E085
+N44E086
+N44E087
+N44E088
+N44E089
+N44E090
+N44E091
+N44E092
+N44E093
+N44E094
+N44E095
+N44E096
+N44E097
+N44E098
+N44E099
+N44E100
+N44E101
+N44E102
+N44E103
+N44E104
+N44E105
+N44E106
+N44E107
+N44E108
+N44E109
+N44E110
+N44E111
+N44E112
+N44E113
+N44E114
+N44E115
+N44E116
+N44E117
+N44E118
+N44E119
+N44E120
+N44E121
+N44E122
+N44E123
+N44E124
+N44E125
+N44E126
+N44E127
+N44E128
+N44E129
+N44E130
+N44E131
+N44E132
+N44E133
+N44E134
+N44E135
+N44E136
+N44E141
+N44E142
+N44E143
+N44E144
+N44E145
+N44E146
+N44E147
+N44W001
+N44W002
+N45E000
+N45E001
+N45E002
+N45E003
+N45E004
+N45E005
+N45E006
+N45E007
+N45E008
+N45E009
+N45E010
+N45E011
+N45E012
+N45E013
+N45E014
+N45E015
+N45E016
+N45E017
+N45E018
+N45E019
+N45E020
+N45E021
+N45E022
+N45E023
+N45E024
+N45E025
+N45E026
+N45E027
+N45E028
+N45E029
+N45E030
+N45E032
+N45E033
+N45E034
+N45E035
+N45E036
+N45E037
+N45E038
+N45E039
+N45E040
+N45E041
+N45E042
+N45E043
+N45E044
+N45E045
+N45E046
+N45E047
+N45E048
+N45E049
+N45E050
+N45E051
+N45E052
+N45E053
+N45E054
+N45E055
+N45E056
+N45E057
+N45E058
+N45E059
+N45E060
+N45E061
+N45E062
+N45E063
+N45E064
+N45E065
+N45E066
+N45E067
+N45E068
+N45E069
+N45E070
+N45E071
+N45E072
+N45E073
+N45E074
+N45E075
+N45E076
+N45E077
+N45E078
+N45E079
+N45E080
+N45E081
+N45E082
+N45E083
+N45E084
+N45E085
+N45E086
+N45E087
+N45E088
+N45E089
+N45E090
+N45E091
+N45E092
+N45E093
+N45E094
+N45E095
+N45E096
+N45E097
+N45E098
+N45E099
+N45E100
+N45E101
+N45E102
+N45E103
+N45E104
+N45E105
+N45E106
+N45E107
+N45E108
+N45E109
+N45E110
+N45E111
+N45E112
+N45E113
+N45E114
+N45E115
+N45E116
+N45E117
+N45E118
+N45E119
+N45E120
+N45E121
+N45E122
+N45E123
+N45E124
+N45E125
+N45E126
+N45E127
+N45E128
+N45E129
+N45E130
+N45E131
+N45E132
+N45E133
+N45E134
+N45E135
+N45E136
+N45E137
+N45E140
+N45E141
+N45E142
+N45E147
+N45E148
+N45E149
+N45E150
+N45W001
+N45W002
+N46E000
+N46E001
+N46E002
+N46E003
+N46E004
+N46E005
+N46E006
+N46E007
+N46E008
+N46E009
+N46E010
+N46E011
+N46E012
+N46E013
+N46E014
+N46E015
+N46E016
+N46E017
+N46E018
+N46E019
+N46E020
+N46E021
+N46E022
+N46E023
+N46E024
+N46E025
+N46E026
+N46E027
+N46E028
+N46E029
+N46E030
+N46E031
+N46E032
+N46E033
+N46E034
+N46E035
+N46E036
+N46E037
+N46E038
+N46E039
+N46E040
+N46E041
+N46E042
+N46E043
+N46E044
+N46E045
+N46E046
+N46E047
+N46E048
+N46E049
+N46E050
+N46E051
+N46E052
+N46E053
+N46E054
+N46E055
+N46E056
+N46E057
+N46E058
+N46E059
+N46E060
+N46E061
+N46E062
+N46E063
+N46E064
+N46E065
+N46E066
+N46E067
+N46E068
+N46E069
+N46E070
+N46E071
+N46E072
+N46E073
+N46E074
+N46E075
+N46E076
+N46E077
+N46E078
+N46E079
+N46E080
+N46E081
+N46E082
+N46E083
+N46E084
+N46E085
+N46E086
+N46E087
+N46E088
+N46E089
+N46E090
+N46E091
+N46E092
+N46E093
+N46E094
+N46E095
+N46E096
+N46E097
+N46E098
+N46E099
+N46E100
+N46E101
+N46E102
+N46E103
+N46E104
+N46E105
+N46E106
+N46E107
+N46E108
+N46E109
+N46E110
+N46E111
+N46E112
+N46E113
+N46E114
+N46E115
+N46E116
+N46E117
+N46E118
+N46E119
+N46E120
+N46E121
+N46E122
+N46E123
+N46E124
+N46E125
+N46E126
+N46E127
+N46E128
+N46E129
+N46E130
+N46E131
+N46E132
+N46E133
+N46E134
+N46E135
+N46E136
+N46E137
+N46E138
+N46E141
+N46E142
+N46E143
+N46E149
+N46E150
+N46E151
+N46E152
+N46W001
+N46W002
+N46W003
+N47E000
+N47E001
+N47E002
+N47E003
+N47E004
+N47E005
+N47E006
+N47E007
+N47E008
+N47E009
+N47E010
+N47E011
+N47E012
+N47E013
+N47E014
+N47E015
+N47E016
+N47E017
+N47E018
+N47E019
+N47E020
+N47E021
+N47E022
+N47E023
+N47E024
+N47E025
+N47E026
+N47E027
+N47E028
+N47E029
+N47E030
+N47E031
+N47E032
+N47E033
+N47E034
+N47E035
+N47E036
+N47E037
+N47E038
+N47E039
+N47E040
+N47E041
+N47E042
+N47E043
+N47E044
+N47E045
+N47E046
+N47E047
+N47E048
+N47E049
+N47E050
+N47E051
+N47E052
+N47E053
+N47E054
+N47E055
+N47E056
+N47E057
+N47E058
+N47E059
+N47E060
+N47E061
+N47E062
+N47E063
+N47E064
+N47E065
+N47E066
+N47E067
+N47E068
+N47E069
+N47E070
+N47E071
+N47E072
+N47E073
+N47E074
+N47E075
+N47E076
+N47E077
+N47E078
+N47E079
+N47E080
+N47E081
+N47E082
+N47E083
+N47E084
+N47E085
+N47E086
+N47E087
+N47E088
+N47E089
+N47E090
+N47E091
+N47E092
+N47E093
+N47E094
+N47E095
+N47E096
+N47E097
+N47E098
+N47E099
+N47E100
+N47E101
+N47E102
+N47E103
+N47E104
+N47E105
+N47E106
+N47E107
+N47E108
+N47E109
+N47E110
+N47E111
+N47E112
+N47E113
+N47E114
+N47E115
+N47E116
+N47E117
+N47E118
+N47E119
+N47E120
+N47E121
+N47E122
+N47E123
+N47E124
+N47E125
+N47E126
+N47E127
+N47E128
+N47E129
+N47E130
+N47E131
+N47E132
+N47E133
+N47E134
+N47E135
+N47E136
+N47E137
+N47E138
+N47E139
+N47E141
+N47E142
+N47E143
+N47E152
+N47E153
+N47W001
+N47W002
+N47W003
+N47W004
+N47W005
+N48E000
+N48E001
+N48E002
+N48E003
+N48E004
+N48E005
+N48E006
+N48E007
+N48E008
+N48E009
+N48E010
+N48E011
+N48E012
+N48E013
+N48E014
+N48E015
+N48E016
+N48E017
+N48E018
+N48E019
+N48E020
+N48E021
+N48E022
+N48E023
+N48E024
+N48E025
+N48E026
+N48E027
+N48E028
+N48E029
+N48E030
+N48E031
+N48E032
+N48E033
+N48E034
+N48E035
+N48E036
+N48E037
+N48E038
+N48E039
+N48E040
+N48E041
+N48E042
+N48E043
+N48E044
+N48E045
+N48E046
+N48E047
+N48E048
+N48E049
+N48E050
+N48E051
+N48E052
+N48E053
+N48E054
+N48E055
+N48E056
+N48E057
+N48E058
+N48E059
+N48E060
+N48E061
+N48E062
+N48E063
+N48E064
+N48E065
+N48E066
+N48E067
+N48E068
+N48E069
+N48E070
+N48E071
+N48E072
+N48E073
+N48E074
+N48E075
+N48E076
+N48E077
+N48E078
+N48E079
+N48E080
+N48E081
+N48E082
+N48E083
+N48E084
+N48E085
+N48E086
+N48E087
+N48E088
+N48E089
+N48E090
+N48E091
+N48E092
+N48E093
+N48E094
+N48E095
+N48E096
+N48E097
+N48E098
+N48E099
+N48E100
+N48E101
+N48E102
+N48E103
+N48E104
+N48E105
+N48E106
+N48E107
+N48E108
+N48E109
+N48E110
+N48E111
+N48E112
+N48E113
+N48E114
+N48E115
+N48E116
+N48E117
+N48E118
+N48E119
+N48E120
+N48E121
+N48E122
+N48E123
+N48E124
+N48E125
+N48E126
+N48E127
+N48E128
+N48E129
+N48E130
+N48E131
+N48E132
+N48E133
+N48E134
+N48E135
+N48E136
+N48E137
+N48E138
+N48E139
+N48E140
+N48E141
+N48E142
+N48E144
+N48E153
+N48E154
+N48W001
+N48W002
+N48W003
+N48W004
+N48W005
+N48W006
+N49E000
+N49E001
+N49E002
+N49E003
+N49E004
+N49E005
+N49E006
+N49E007
+N49E008
+N49E009
+N49E010
+N49E011
+N49E012
+N49E013
+N49E014
+N49E015
+N49E016
+N49E017
+N49E018
+N49E019
+N49E020
+N49E021
+N49E022
+N49E023
+N49E024
+N49E025
+N49E026
+N49E027
+N49E028
+N49E029
+N49E030
+N49E031
+N49E032
+N49E033
+N49E034
+N49E035
+N49E036
+N49E037
+N49E038
+N49E039
+N49E040
+N49E041
+N49E042
+N49E043
+N49E044
+N49E045
+N49E046
+N49E047
+N49E048
+N49E049
+N49E050
+N49E051
+N49E052
+N49E053
+N49E054
+N49E055
+N49E056
+N49E057
+N49E058
+N49E059
+N49E060
+N49E061
+N49E062
+N49E063
+N49E064
+N49E065
+N49E066
+N49E067
+N49E068
+N49E069
+N49E070
+N49E071
+N49E072
+N49E073
+N49E074
+N49E075
+N49E076
+N49E077
+N49E078
+N49E079
+N49E080
+N49E081
+N49E082
+N49E083
+N49E084
+N49E085
+N49E086
+N49E087
+N49E088
+N49E089
+N49E090
+N49E091
+N49E092
+N49E093
+N49E094
+N49E095
+N49E096
+N49E097
+N49E098
+N49E099
+N49E100
+N49E101
+N49E102
+N49E103
+N49E104
+N49E105
+N49E106
+N49E107
+N49E108
+N49E109
+N49E110
+N49E111
+N49E112
+N49E113
+N49E114
+N49E115
+N49E116
+N49E117
+N49E118
+N49E119
+N49E120
+N49E121
+N49E122
+N49E123
+N49E124
+N49E125
+N49E126
+N49E127
+N49E128
+N49E129
+N49E130
+N49E131
+N49E132
+N49E133
+N49E134
+N49E135
+N49E136
+N49E137
+N49E138
+N49E139
+N49E140
+N49E142
+N49E143
+N49E144
+N49E154
+N49E155
+N49W001
+N49W002
+N49W003
+N49W006
+N49W007
+N50E000
+N50E001
+N50E002
+N50E003
+N50E004
+N50E005
+N50E006
+N50E007
+N50E008
+N50E009
+N50E010
+N50E011
+N50E012
+N50E013
+N50E014
+N50E015
+N50E016
+N50E017
+N50E018
+N50E019
+N50E020
+N50E021
+N50E022
+N50E023
+N50E024
+N50E025
+N50E026
+N50E027
+N50E028
+N50E029
+N50E030
+N50E031
+N50E032
+N50E033
+N50E034
+N50E035
+N50E036
+N50E037
+N50E038
+N50E039
+N50E040
+N50E041
+N50E042
+N50E043
+N50E044
+N50E045
+N50E046
+N50E047
+N50E048
+N50E049
+N50E050
+N50E051
+N50E052
+N50E053
+N50E054
+N50E055
+N50E056
+N50E057
+N50E058
+N50E059
+N50E060
+N50E061
+N50E062
+N50E063
+N50E064
+N50E065
+N50E066
+N50E067
+N50E068
+N50E069
+N50E070
+N50E071
+N50E072
+N50E073
+N50E074
+N50E075
+N50E076
+N50E077
+N50E078
+N50E079
+N50E080
+N50E081
+N50E082
+N50E083
+N50E084
+N50E085
+N50E086
+N50E087
+N50E088
+N50E089
+N50E090
+N50E091
+N50E092
+N50E093
+N50E094
+N50E095
+N50E096
+N50E097
+N50E098
+N50E099
+N50E100
+N50E101
+N50E102
+N50E103
+N50E104
+N50E105
+N50E106
+N50E107
+N50E108
+N50E109
+N50E110
+N50E111
+N50E112
+N50E113
+N50E114
+N50E115
+N50E116
+N50E117
+N50E118
+N50E119
+N50E120
+N50E121
+N50E122
+N50E123
+N50E124
+N50E125
+N50E126
+N50E127
+N50E128
+N50E129
+N50E130
+N50E131
+N50E132
+N50E133
+N50E134
+N50E135
+N50E136
+N50E137
+N50E138
+N50E139
+N50E140
+N50E142
+N50E143
+N50E154
+N50E155
+N50E156
+N50W001
+N50W002
+N50W003
+N50W004
+N50W005
+N50W006
+N51E000
+N51E001
+N51E002
+N51E003
+N51E004
+N51E005
+N51E006
+N51E007
+N51E008
+N51E009
+N51E010
+N51E011
+N51E012
+N51E013
+N51E014
+N51E015
+N51E016
+N51E017
+N51E018
+N51E019
+N51E020
+N51E021
+N51E022
+N51E023
+N51E024
+N51E025
+N51E026
+N51E027
+N51E028
+N51E029
+N51E030
+N51E031
+N51E032
+N51E033
+N51E034
+N51E035
+N51E036
+N51E037
+N51E038
+N51E039
+N51E040
+N51E041
+N51E042
+N51E043
+N51E044
+N51E045
+N51E046
+N51E047
+N51E048
+N51E049
+N51E050
+N51E051
+N51E052
+N51E053
+N51E054
+N51E055
+N51E056
+N51E057
+N51E058
+N51E059
+N51E060
+N51E061
+N51E062
+N51E063
+N51E064
+N51E065
+N51E066
+N51E067
+N51E068
+N51E069
+N51E070
+N51E071
+N51E072
+N51E073
+N51E074
+N51E075
+N51E076
+N51E077
+N51E078
+N51E079
+N51E080
+N51E081
+N51E082
+N51E083
+N51E084
+N51E085
+N51E086
+N51E087
+N51E088
+N51E089
+N51E090
+N51E091
+N51E092
+N51E093
+N51E094
+N51E095
+N51E096
+N51E097
+N51E098
+N51E099
+N51E100
+N51E101
+N51E102
+N51E103
+N51E104
+N51E105
+N51E106
+N51E107
+N51E108
+N51E109
+N51E110
+N51E111
+N51E112
+N51E113
+N51E114
+N51E115
+N51E116
+N51E117
+N51E118
+N51E119
+N51E120
+N51E121
+N51E122
+N51E123
+N51E124
+N51E125
+N51E126
+N51E127
+N51E128
+N51E129
+N51E130
+N51E131
+N51E132
+N51E133
+N51E134
+N51E135
+N51E136
+N51E137
+N51E138
+N51E139
+N51E140
+N51E141
+N51E142
+N51E143
+N51E156
+N51E157
+N51E158
+N51W001
+N51W002
+N51W003
+N51W004
+N51W005
+N51W006
+N51W008
+N51W009
+N51W010
+N51W011
+N52E000
+N52E001
+N52E004
+N52E005
+N52E006
+N52E007
+N52E008
+N52E009
+N52E010
+N52E011
+N52E012
+N52E013
+N52E014
+N52E015
+N52E016
+N52E017
+N52E018
+N52E019
+N52E020
+N52E021
+N52E022
+N52E023
+N52E024
+N52E025
+N52E026
+N52E027
+N52E028
+N52E029
+N52E030
+N52E031
+N52E032
+N52E033
+N52E034
+N52E035
+N52E036
+N52E037
+N52E038
+N52E039
+N52E040
+N52E041
+N52E042
+N52E043
+N52E044
+N52E045
+N52E046
+N52E047
+N52E048
+N52E049
+N52E050
+N52E051
+N52E052
+N52E053
+N52E054
+N52E055
+N52E056
+N52E057
+N52E058
+N52E059
+N52E060
+N52E061
+N52E062
+N52E063
+N52E064
+N52E065
+N52E066
+N52E067
+N52E068
+N52E069
+N52E070
+N52E071
+N52E072
+N52E073
+N52E074
+N52E075
+N52E076
+N52E077
+N52E078
+N52E079
+N52E080
+N52E081
+N52E082
+N52E083
+N52E084
+N52E085
+N52E086
+N52E087
+N52E088
+N52E089
+N52E090
+N52E091
+N52E092
+N52E093
+N52E094
+N52E095
+N52E096
+N52E097
+N52E098
+N52E099
+N52E100
+N52E101
+N52E102
+N52E103
+N52E104
+N52E105
+N52E106
+N52E107
+N52E108
+N52E109
+N52E110
+N52E111
+N52E112
+N52E113
+N52E114
+N52E115
+N52E116
+N52E117
+N52E118
+N52E119
+N52E120
+N52E121
+N52E122
+N52E123
+N52E124
+N52E125
+N52E126
+N52E127
+N52E128
+N52E129
+N52E130
+N52E131
+N52E132
+N52E133
+N52E134
+N52E135
+N52E136
+N52E137
+N52E138
+N52E139
+N52E140
+N52E141
+N52E142
+N52E143
+N52E156
+N52E157
+N52E158
+N52W001
+N52W002
+N52W003
+N52W004
+N52W005
+N52W006
+N52W007
+N52W008
+N52W009
+N52W010
+N52W011
+N53E000
+N53E004
+N53E005
+N53E006
+N53E007
+N53E008
+N53E009
+N53E010
+N53E011
+N53E012
+N53E013
+N53E014
+N53E015
+N53E016
+N53E017
+N53E018
+N53E019
+N53E020
+N53E021
+N53E022
+N53E023
+N53E024
+N53E025
+N53E026
+N53E027
+N53E028
+N53E029
+N53E030
+N53E031
+N53E032
+N53E033
+N53E034
+N53E035
+N53E036
+N53E037
+N53E038
+N53E039
+N53E040
+N53E041
+N53E042
+N53E043
+N53E044
+N53E045
+N53E046
+N53E047
+N53E048
+N53E049
+N53E050
+N53E051
+N53E052
+N53E053
+N53E054
+N53E055
+N53E056
+N53E057
+N53E058
+N53E059
+N53E060
+N53E061
+N53E062
+N53E063
+N53E064
+N53E065
+N53E066
+N53E067
+N53E068
+N53E069
+N53E070
+N53E071
+N53E072
+N53E073
+N53E074
+N53E075
+N53E076
+N53E077
+N53E078
+N53E079
+N53E080
+N53E081
+N53E082
+N53E083
+N53E084
+N53E085
+N53E086
+N53E087
+N53E088
+N53E089
+N53E090
+N53E091
+N53E092
+N53E093
+N53E094
+N53E095
+N53E096
+N53E097
+N53E098
+N53E099
+N53E100
+N53E101
+N53E102
+N53E103
+N53E104
+N53E105
+N53E106
+N53E107
+N53E108
+N53E109
+N53E110
+N53E111
+N53E112
+N53E113
+N53E114
+N53E115
+N53E116
+N53E117
+N53E118
+N53E119
+N53E120
+N53E121
+N53E122
+N53E123
+N53E124
+N53E125
+N53E126
+N53E127
+N53E128
+N53E129
+N53E130
+N53E131
+N53E132
+N53E133
+N53E134
+N53E135
+N53E136
+N53E137
+N53E138
+N53E139
+N53E140
+N53E141
+N53E142
+N53E143
+N53E155
+N53E156
+N53E157
+N53E158
+N53E159
+N53E160
+N53W001
+N53W002
+N53W003
+N53W004
+N53W005
+N53W006
+N53W007
+N53W008
+N53W009
+N53W010
+N53W011
+N54E007
+N54E008
+N54E009
+N54E010
+N54E011
+N54E012
+N54E013
+N54E014
+N54E015
+N54E016
+N54E017
+N54E018
+N54E019
+N54E020
+N54E021
+N54E022
+N54E023
+N54E024
+N54E025
+N54E026
+N54E027
+N54E028
+N54E029
+N54E030
+N54E031
+N54E032
+N54E033
+N54E034
+N54E035
+N54E036
+N54E037
+N54E038
+N54E039
+N54E040
+N54E041
+N54E042
+N54E043
+N54E044
+N54E045
+N54E046
+N54E047
+N54E048
+N54E049
+N54E050
+N54E051
+N54E052
+N54E053
+N54E054
+N54E055
+N54E056
+N54E057
+N54E058
+N54E059
+N54E060
+N54E061
+N54E062
+N54E063
+N54E064
+N54E065
+N54E066
+N54E067
+N54E068
+N54E069
+N54E070
+N54E071
+N54E072
+N54E073
+N54E074
+N54E075
+N54E076
+N54E077
+N54E078
+N54E079
+N54E080
+N54E081
+N54E082
+N54E083
+N54E084
+N54E085
+N54E086
+N54E087
+N54E088
+N54E089
+N54E090
+N54E091
+N54E092
+N54E093
+N54E094
+N54E095
+N54E096
+N54E097
+N54E098
+N54E099
+N54E100
+N54E101
+N54E102
+N54E103
+N54E104
+N54E105
+N54E106
+N54E107
+N54E108
+N54E109
+N54E110
+N54E111
+N54E112
+N54E113
+N54E114
+N54E115
+N54E116
+N54E117
+N54E118
+N54E119
+N54E120
+N54E121
+N54E122
+N54E123
+N54E124
+N54E125
+N54E126
+N54E127
+N54E128
+N54E129
+N54E130
+N54E131
+N54E132
+N54E133
+N54E134
+N54E135
+N54E136
+N54E137
+N54E138
+N54E139
+N54E140
+N54E142
+N54E155
+N54E156
+N54E157
+N54E158
+N54E159
+N54E160
+N54E161
+N54E162
+N54E166
+N54E167
+N54E168
+N54W001
+N54W002
+N54W003
+N54W004
+N54W005
+N54W006
+N54W007
+N54W008
+N54W009
+N54W010
+N54W011
+N55E008
+N55E009
+N55E010
+N55E011
+N55E012
+N55E013
+N55E014
+N55E015
+N55E020
+N55E021
+N55E022
+N55E023
+N55E024
+N55E025
+N55E026
+N55E027
+N55E028
+N55E029
+N55E030
+N55E031
+N55E032
+N55E033
+N55E034
+N55E035
+N55E036
+N55E037
+N55E038
+N55E039
+N55E040
+N55E041
+N55E042
+N55E043
+N55E044
+N55E045
+N55E046
+N55E047
+N55E048
+N55E049
+N55E050
+N55E051
+N55E052
+N55E053
+N55E054
+N55E055
+N55E056
+N55E057
+N55E058
+N55E059
+N55E060
+N55E061
+N55E062
+N55E063
+N55E064
+N55E065
+N55E066
+N55E067
+N55E068
+N55E069
+N55E070
+N55E071
+N55E072
+N55E073
+N55E074
+N55E075
+N55E076
+N55E077
+N55E078
+N55E079
+N55E080
+N55E081
+N55E082
+N55E083
+N55E084
+N55E085
+N55E086
+N55E087
+N55E088
+N55E089
+N55E090
+N55E091
+N55E092
+N55E093
+N55E094
+N55E095
+N55E096
+N55E097
+N55E098
+N55E099
+N55E100
+N55E101
+N55E102
+N55E103
+N55E104
+N55E105
+N55E106
+N55E107
+N55E108
+N55E109
+N55E110
+N55E111
+N55E112
+N55E113
+N55E114
+N55E115
+N55E116
+N55E117
+N55E118
+N55E119
+N55E120
+N55E121
+N55E122
+N55E123
+N55E124
+N55E125
+N55E126
+N55E127
+N55E128
+N55E129
+N55E130
+N55E131
+N55E132
+N55E133
+N55E134
+N55E135
+N55E136
+N55E137
+N55E138
+N55E155
+N55E156
+N55E157
+N55E158
+N55E159
+N55E160
+N55E161
+N55E162
+N55E165
+N55E166
+N55W002
+N55W003
+N55W004
+N55W005
+N55W006
+N55W007
+N55W008
+N55W009
+N56E008
+N56E009
+N56E010
+N56E011
+N56E012
+N56E013
+N56E014
+N56E015
+N56E016
+N56E018
+N56E020
+N56E021
+N56E022
+N56E023
+N56E024
+N56E025
+N56E026
+N56E027
+N56E028
+N56E029
+N56E030
+N56E031
+N56E032
+N56E033
+N56E034
+N56E035
+N56E036
+N56E037
+N56E038
+N56E039
+N56E040
+N56E041
+N56E042
+N56E043
+N56E044
+N56E045
+N56E046
+N56E047
+N56E048
+N56E049
+N56E050
+N56E051
+N56E052
+N56E053
+N56E054
+N56E055
+N56E056
+N56E057
+N56E058
+N56E059
+N56E060
+N56E061
+N56E062
+N56E063
+N56E064
+N56E065
+N56E066
+N56E067
+N56E068
+N56E069
+N56E070
+N56E071
+N56E072
+N56E073
+N56E074
+N56E075
+N56E076
+N56E077
+N56E078
+N56E079
+N56E080
+N56E081
+N56E082
+N56E083
+N56E084
+N56E085
+N56E086
+N56E087
+N56E088
+N56E089
+N56E090
+N56E091
+N56E092
+N56E093
+N56E094
+N56E095
+N56E096
+N56E097
+N56E098
+N56E099
+N56E100
+N56E101
+N56E102
+N56E103
+N56E104
+N56E105
+N56E106
+N56E107
+N56E108
+N56E109
+N56E110
+N56E111
+N56E112
+N56E113
+N56E114
+N56E115
+N56E116
+N56E117
+N56E118
+N56E119
+N56E120
+N56E121
+N56E122
+N56E123
+N56E124
+N56E125
+N56E126
+N56E127
+N56E128
+N56E129
+N56E130
+N56E131
+N56E132
+N56E133
+N56E134
+N56E135
+N56E136
+N56E137
+N56E138
+N56E143
+N56E155
+N56E156
+N56E157
+N56E158
+N56E159
+N56E160
+N56E161
+N56E162
+N56E163
+N56W003
+N56W004
+N56W005
+N56W006
+N56W007
+N56W008
+N57E006
+N57E007
+N57E008
+N57E009
+N57E010
+N57E011
+N57E012
+N57E013
+N57E014
+N57E015
+N57E016
+N57E017
+N57E018
+N57E019
+N57E021
+N57E022
+N57E023
+N57E024
+N57E025
+N57E026
+N57E027
+N57E028
+N57E029
+N57E030
+N57E031
+N57E032
+N57E033
+N57E034
+N57E035
+N57E036
+N57E037
+N57E038
+N57E039
+N57E040
+N57E041
+N57E042
+N57E043
+N57E044
+N57E045
+N57E046
+N57E047
+N57E048
+N57E049
+N57E050
+N57E051
+N57E052
+N57E053
+N57E054
+N57E055
+N57E056
+N57E057
+N57E058
+N57E059
+N57E060
+N57E061
+N57E062
+N57E063
+N57E064
+N57E065
+N57E066
+N57E067
+N57E068
+N57E069
+N57E070
+N57E071
+N57E072
+N57E073
+N57E074
+N57E075
+N57E076
+N57E077
+N57E078
+N57E079
+N57E080
+N57E081
+N57E082
+N57E083
+N57E084
+N57E085
+N57E086
+N57E087
+N57E088
+N57E089
+N57E090
+N57E091
+N57E092
+N57E093
+N57E094
+N57E095
+N57E096
+N57E097
+N57E098
+N57E099
+N57E100
+N57E101
+N57E102
+N57E103
+N57E104
+N57E105
+N57E106
+N57E107
+N57E108
+N57E109
+N57E110
+N57E111
+N57E112
+N57E113
+N57E114
+N57E115
+N57E116
+N57E117
+N57E118
+N57E119
+N57E120
+N57E121
+N57E122
+N57E123
+N57E124
+N57E125
+N57E126
+N57E127
+N57E128
+N57E129
+N57E130
+N57E131
+N57E132
+N57E133
+N57E134
+N57E135
+N57E136
+N57E137
+N57E138
+N57E139
+N57E140
+N57E156
+N57E157
+N57E158
+N57E159
+N57E160
+N57E161
+N57E162
+N57E163
+N57W002
+N57W003
+N57W004
+N57W005
+N57W006
+N57W007
+N57W008
+N57W009
+N57W014
+N58E005
+N58E006
+N58E007
+N58E008
+N58E009
+N58E010
+N58E011
+N58E012
+N58E013
+N58E014
+N58E015
+N58E016
+N58E017
+N58E018
+N58E019
+N58E021
+N58E022
+N58E023
+N58E024
+N58E025
+N58E026
+N58E027
+N58E028
+N58E029
+N58E030
+N58E031
+N58E032
+N58E033
+N58E034
+N58E035
+N58E036
+N58E037
+N58E038
+N58E039
+N58E040
+N58E041
+N58E042
+N58E043
+N58E044
+N58E045
+N58E046
+N58E047
+N58E048
+N58E049
+N58E050
+N58E051
+N58E052
+N58E053
+N58E054
+N58E055
+N58E056
+N58E057
+N58E058
+N58E059
+N58E060
+N58E061
+N58E062
+N58E063
+N58E064
+N58E065
+N58E066
+N58E067
+N58E068
+N58E069
+N58E070
+N58E071
+N58E072
+N58E073
+N58E074
+N58E075
+N58E076
+N58E077
+N58E078
+N58E079
+N58E080
+N58E081
+N58E082
+N58E083
+N58E084
+N58E085
+N58E086
+N58E087
+N58E088
+N58E089
+N58E090
+N58E091
+N58E092
+N58E093
+N58E094
+N58E095
+N58E096
+N58E097
+N58E098
+N58E099
+N58E100
+N58E101
+N58E102
+N58E103
+N58E104
+N58E105
+N58E106
+N58E107
+N58E108
+N58E109
+N58E110
+N58E111
+N58E112
+N58E113
+N58E114
+N58E115
+N58E116
+N58E117
+N58E118
+N58E119
+N58E120
+N58E121
+N58E122
+N58E123
+N58E124
+N58E125
+N58E126
+N58E127
+N58E128
+N58E129
+N58E130
+N58E131
+N58E132
+N58E133
+N58E134
+N58E135
+N58E136
+N58E137
+N58E138
+N58E139
+N58E140
+N58E141
+N58E142
+N58E150
+N58E151
+N58E152
+N58E157
+N58E158
+N58E159
+N58E160
+N58E161
+N58E162
+N58E163
+N58E164
+N58W003
+N58W004
+N58W005
+N58W006
+N58W007
+N58W008
+N59E004
+N59E005
+N59E006
+N59E007
+N59E008
+N59E009
+N59E010
+N59E011
+N59E012
+N59E013
+N59E014
+N59E015
+N59E016
+N59E017
+N59E018
+N59E019
+N59E020
+N59E021
+N59E022
+N59E023
+N59E024
+N59E025
+N59E026
+N59E027
+N59E028
+N59E029
+N59E030
+N59E031
+N59E032
+N59E033
+N59E034
+N59E035
+N59E036
+N59E037
+N59E038
+N59E039
+N59E040
+N59E041
+N59E042
+N59E043
+N59E044
+N59E045
+N59E046
+N59E047
+N59E048
+N59E049
+N59E050
+N59E051
+N59E052
+N59E053
+N59E054
+N59E055
+N59E056
+N59E057
+N59E058
+N59E059
+N59E060
+N59E061
+N59E062
+N59E063
+N59E064
+N59E065
+N59E066
+N59E067
+N59E068
+N59E069
+N59E070
+N59E071
+N59E072
+N59E073
+N59E074
+N59E075
+N59E076
+N59E077
+N59E078
+N59E079
+N59E080
+N59E081
+N59E082
+N59E083
+N59E084
+N59E085
+N59E086
+N59E087
+N59E088
+N59E089
+N59E090
+N59E091
+N59E092
+N59E093
+N59E094
+N59E095
+N59E096
+N59E097
+N59E098
+N59E099
+N59E100
+N59E101
+N59E102
+N59E103
+N59E104
+N59E105
+N59E106
+N59E107
+N59E108
+N59E109
+N59E110
+N59E111
+N59E112
+N59E113
+N59E114
+N59E115
+N59E116
+N59E117
+N59E118
+N59E119
+N59E120
+N59E121
+N59E122
+N59E123
+N59E124
+N59E125
+N59E126
+N59E127
+N59E128
+N59E129
+N59E130
+N59E131
+N59E132
+N59E133
+N59E134
+N59E135
+N59E136
+N59E137
+N59E138
+N59E139
+N59E140
+N59E141
+N59E142
+N59E143
+N59E144
+N59E145
+N59E146
+N59E147
+N59E148
+N59E149
+N59E150
+N59E151
+N59E152
+N59E153
+N59E154
+N59E155
+N59E159
+N59E160
+N59E161
+N59E162
+N59E163
+N59E164
+N59E165
+N59E166
+N59W002
+N59W003
+N59W004
+N59W005
+N59W006
+N59W007
+N60E004
+N60E005
+N60E006
+N60E007
+N60E008
+N60E009
+N60E010
+N60E011
+N60E012
+N60E013
+N60E014
+N60E015
+N60E016
+N60E017
+N60E018
+N60E019
+N60E020
+N60E021
+N60E022
+N60E023
+N60E024
+N60E025
+N60E026
+N60E027
+N60E028
+N60E029
+N60E030
+N60E031
+N60E032
+N60E033
+N60E034
+N60E035
+N60E036
+N60E037
+N60E038
+N60E039
+N60E040
+N60E041
+N60E042
+N60E043
+N60E044
+N60E045
+N60E046
+N60E047
+N60E048
+N60E049
+N60E050
+N60E051
+N60E052
+N60E053
+N60E054
+N60E055
+N60E056
+N60E057
+N60E058
+N60E059
+N60E060
+N60E061
+N60E062
+N60E063
+N60E064
+N60E065
+N60E066
+N60E067
+N60E068
+N60E069
+N60E070
+N60E071
+N60E072
+N60E073
+N60E074
+N60E075
+N60E076
+N60E077
+N60E078
+N60E079
+N60E080
+N60E081
+N60E082
+N60E083
+N60E084
+N60E085
+N60E086
+N60E087
+N60E088
+N60E089
+N60E090
+N60E091
+N60E092
+N60E093
+N60E094
+N60E095
+N60E096
+N60E097
+N60E098
+N60E099
+N60E100
+N60E101
+N60E102
+N60E103
+N60E104
+N60E105
+N60E106
+N60E107
+N60E108
+N60E109
+N60E110
+N60E111
+N60E112
+N60E113
+N60E114
+N60E115
+N60E116
+N60E117
+N60E118
+N60E119
+N60E120
+N60E121
+N60E122
+N60E123
+N60E124
+N60E125
+N60E126
+N60E127
+N60E128
+N60E129
+N60E130
+N60E131
+N60E132
+N60E133
+N60E134
+N60E135
+N60E136
+N60E137
+N60E138
+N60E139
+N60E140
+N60E141
+N60E142
+N60E143
+N60E144
+N60E145
+N60E146
+N60E147
+N60E148
+N60E149
+N60E150
+N60E151
+N60E152
+N60E153
+N60E154
+N60E155
+N60E156
+N60E159
+N60E160
+N60E161
+N60E162
+N60E163
+N60E164
+N60E165
+N60E166
+N60E167
+N60E168
+N60E169
+N60E170
+N60E171
+N60E172
+N60W001
+N60W002
+N60W003
+S01E073
+S01E098
+S01E099
+S01E100
+S01E101
+S01E102
+S01E103
+S01E104
+S01E105
+S01E109
+S01E110
+S01E111
+S01E112
+S01E113
+S01E114
+S01E115
+S01E116
+S01E117
+S01E119
+S01E120
+S01E121
+S01E122
+S01E123
+S01E127
+S01E128
+S01E129
+S01E130
+S01E131
+S01E132
+S01E133
+S01E134
+S01E135
+S01E136
+S01E145
+S01E166
+S01E169
+S01E174
+S01W161
+S02E098
+S02E099
+S02E100
+S02E101
+S02E102
+S02E103
+S02E104
+S02E105
+S02E106
+S02E108
+S02E109
+S02E110
+S02E111
+S02E112
+S02E113
+S02E114
+S02E115
+S02E116
+S02E117
+S02E119
+S02E120
+S02E121
+S02E122
+S02E123
+S02E124
+S02E125
+S02E126
+S02E127
+S02E128
+S02E129
+S02E130
+S02E131
+S02E132
+S02E133
+S02E134
+S02E135
+S02E136
+S02E137
+S02E138
+S02E139
+S02E142
+S02E143
+S02E144
+S02E145
+S02E146
+S02E147
+S02E148
+S02E149
+S02E150
+S02E174
+S02E175
+S02E176
+S03E099
+S03E100
+S03E101
+S03E102
+S03E103
+S03E104
+S03E105
+S03E106
+S03E107
+S03E108
+S03E110
+S03E111
+S03E112
+S03E113
+S03E114
+S03E115
+S03E116
+S03E117
+S03E118
+S03E119
+S03E120
+S03E121
+S03E122
+S03E123
+S03E124
+S03E125
+S03E126
+S03E127
+S03E128
+S03E129
+S03E130
+S03E131
+S03E132
+S03E133
+S03E134
+S03E135
+S03E136
+S03E137
+S03E138
+S03E139
+S03E140
+S03E141
+S03E142
+S03E145
+S03E146
+S03E147
+S03E148
+S03E149
+S03E150
+S03E151
+S03E152
+S03E175
+S03E176
+S03W172
+S04E100
+S04E101
+S04E102
+S04E103
+S04E104
+S04E105
+S04E106
+S04E107
+S04E108
+S04E110
+S04E111
+S04E112
+S04E113
+S04E114
+S04E115
+S04E116
+S04E117
+S04E118
+S04E119
+S04E120
+S04E121
+S04E122
+S04E123
+S04E125
+S04E126
+S04E127
+S04E128
+S04E129
+S04E130
+S04E131
+S04E132
+S04E133
+S04E134
+S04E135
+S04E136
+S04E137
+S04E138
+S04E139
+S04E140
+S04E141
+S04E142
+S04E143
+S04E144
+S04E150
+S04E151
+S04E152
+S04E153
+S04E154
+S04W155
+S04W171
+S04W172
+S04W175
+S05E101
+S05E102
+S05E103
+S05E104
+S05E105
+S05E114
+S05E115
+S05E116
+S05E119
+S05E120
+S05E121
+S05E122
+S05E123
+S05E129
+S05E130
+S05E131
+S05E132
+S05E133
+S05E134
+S05E135
+S05E136
+S05E137
+S05E138
+S05E139
+S05E140
+S05E141
+S05E142
+S05E143
+S05E144
+S05E145
+S05E146
+S05E149
+S05E150
+S05E151
+S05E152
+S05E153
+S05E154
+S05E155
+S05E156
+S05E157
+S05E159
+S05W155
+S05W172
+S05W173
+S05W175
+S06E071
+S06E072
+S06E102
+S06E103
+S06E104
+S06E105
+S06E106
+S06E107
+S06E108
+S06E110
+S06E112
+S06E114
+S06E117
+S06E118
+S06E119
+S06E120
+S06E121
+S06E122
+S06E123
+S06E124
+S06E127
+S06E130
+S06E131
+S06E132
+S06E133
+S06E134
+S06E137
+S06E138
+S06E139
+S06E140
+S06E141
+S06E142
+S06E143
+S06E144
+S06E145
+S06E146
+S06E147
+S06E148
+S06E149
+S06E150
+S06E151
+S06E152
+S06E154
+S06E155
+S06E159
+S06E176
+S06W156
+S07E071
+S07E105
+S07E106
+S07E107
+S07E108
+S07E109
+S07E110
+S07E111
+S07E112
+S07E113
+S07E114
+S07E115
+S07E116
+S07E118
+S07E119
+S07E120
+S07E121
+S07E122
+S07E124
+S07E126
+S07E129
+S07E130
+S07E131
+S07E132
+S07E134
+S07E138
+S07E139
+S07E140
+S07E141
+S07E142
+S07E143
+S07E144
+S07E145
+S07E146
+S07E147
+S07E148
+S07E149
+S07E150
+S07E151
+S07E154
+S07E155
+S07E156
+S07E157
+S07E176
+S07E177
+S08E072
+S08E105
+S08E106
+S08E107
+S08E108
+S08E109
+S08E110
+S08E111
+S08E112
+S08E113
+S08E114
+S08E115
+S08E117
+S08E118
+S08E120
+S08E121
+S08E122
+S08E123
+S08E125
+S08E126
+S08E127
+S08E128
+S08E129
+S08E130
+S08E131
+S08E134
+S08E137
+S08E138
+S08E139
+S08E140
+S08E141
+S08E142
+S08E143
+S08E144
+S08E145
+S08E146
+S08E147
+S08E155
+S08E156
+S08E157
+S08E158
+S08E159
+S08E160
+S08E177
+S08E178
+S08W141
+S09E110
+S09E111
+S09E112
+S09E113
+S09E114
+S09E115
+S09E116
+S09E117
+S09E118
+S09E119
+S09E120
+S09E121
+S09E122
+S09E123
+S09E124
+S09E125
+S09E126
+S09E127
+S09E128
+S09E129
+S09E130
+S09E131
+S09E137
+S09E138
+S09E139
+S09E140
+S09E141
+S09E142
+S09E143
+S09E145
+S09E146
+S09E147
+S09E148
+S09E149
+S09E150
+S09E151
+S09E152
+S09E156
+S09E157
+S09E158
+S09E159
+S09E160
+S09E161
+S09E178
+S09E179
+S09W140
+S09W141
+S09W158
+S09W159
+S09W173
+S10E116
+S10E117
+S10E118
+S10E119
+S10E120
+S10E123
+S10E124
+S10E125
+S10E126
+S10E140
+S10E141
+S10E142
+S10E143
+S10E144
+S10E146
+S10E147
+S10E148
+S10E149
+S10E150
+S10E151
+S10E152
+S10E153
+S10E158
+S10E159
+S10E160
+S10E161
+S10E167
+S10E179
+S10W139
+S10W140
+S10W141
+S10W151
+S10W158
+S10W159
+S10W162
+S10W172
+S11E105
+S12E096
+S13E096
+
diff --git a/tim/prune/function/srtm/gen/tiles2.txt b/tim/prune/function/srtm/gen/tiles2.txt
new file mode 100644 (file)
index 0000000..f60c70b
--- /dev/null
@@ -0,0 +1,1917 @@
+North_America
+N10W110
+N15W062
+N15W064
+N15W079
+N15W080
+N15W083
+N15W084
+N15W085
+N15W086
+N15W087
+N15W088
+N15W089
+N15W090
+N15W091
+N15W092
+N15W093
+N15W094
+N15W096
+N15W097
+N15W098
+N16W062
+N16W063
+N16W086
+N16W087
+N16W088
+N16W089
+N16W090
+N16W091
+N16W092
+N16W093
+N16W094
+N16W095
+N16W096
+N16W097
+N16W098
+N16W099
+N16W100
+N16W101
+N17W062
+N17W063
+N17W064
+N17W065
+N17W066
+N17W067
+N17W068
+N17W072
+N17W076
+N17W077
+N17W078
+N17W084
+N17W088
+N17W089
+N17W090
+N17W091
+N17W092
+N17W093
+N17W094
+N17W095
+N17W096
+N17W097
+N17W098
+N17W099
+N17W100
+N17W101
+N17W102
+N17W103
+N18W063
+N18W064
+N18W065
+N18W066
+N18W067
+N18W068
+N18W069
+N18W070
+N18W071
+N18W072
+N18W073
+N18W074
+N18W075
+N18W076
+N18W077
+N18W078
+N18W079
+N18W088
+N18W089
+N18W090
+N18W091
+N18W092
+N18W093
+N18W094
+N18W095
+N18W096
+N18W097
+N18W098
+N18W099
+N18W100
+N18W101
+N18W102
+N18W103
+N18W104
+N18W105
+N18W111
+N18W112
+N18W115
+N19W069
+N19W070
+N19W071
+N19W072
+N19W073
+N19W074
+N19W075
+N19W076
+N19W077
+N19W078
+N19W080
+N19W081
+N19W082
+N19W088
+N19W089
+N19W090
+N19W091
+N19W092
+N19W096
+N19W097
+N19W098
+N19W099
+N19W100
+N19W101
+N19W102
+N19W103
+N19W104
+N19W105
+N19W106
+N19W111
+N20W073
+N20W074
+N20W075
+N20W076
+N20W077
+N20W078
+N20W079
+N20W080
+N20W087
+N20W088
+N20W089
+N20W090
+N20W091
+N20W092
+N20W093
+N20W097
+N20W098
+N20W099
+N20W100
+N20W101
+N20W102
+N20W103
+N20W104
+N20W105
+N20W106
+N21W072
+N21W073
+N21W074
+N21W076
+N21W077
+N21W078
+N21W079
+N21W080
+N21W081
+N21W082
+N21W083
+N21W084
+N21W085
+N21W087
+N21W088
+N21W089
+N21W090
+N21W091
+N21W098
+N21W099
+N21W100
+N21W101
+N21W102
+N21W103
+N21W104
+N21W105
+N21W106
+N21W107
+N22W073
+N22W074
+N22W075
+N22W076
+N22W078
+N22W079
+N22W080
+N22W081
+N22W082
+N22W083
+N22W084
+N22W085
+N22W090
+N22W092
+N22W098
+N22W099
+N22W100
+N22W101
+N22W102
+N22W103
+N22W104
+N22W105
+N22W106
+N22W107
+N22W110
+N22W111
+N23W074
+N23W075
+N23W076
+N23W077
+N23W078
+N23W080
+N23W081
+N23W082
+N23W083
+N23W084
+N23W098
+N23W099
+N23W100
+N23W101
+N23W102
+N23W103
+N23W104
+N23W105
+N23W106
+N23W107
+N23W108
+N23W110
+N23W111
+N24W075
+N24W076
+N24W077
+N24W078
+N24W079
+N24W080
+N24W081
+N24W082
+N24W083
+N24W098
+N24W099
+N24W100
+N24W101
+N24W102
+N24W103
+N24W104
+N24W105
+N24W106
+N24W107
+N24W108
+N24W109
+N24W110
+N24W111
+N24W112
+N24W113
+N24W116
+N25W077
+N25W078
+N25W079
+N25W080
+N25W081
+N25W082
+N25W098
+N25W099
+N25W100
+N25W101
+N25W102
+N25W103
+N25W104
+N25W105
+N25W106
+N25W107
+N25W108
+N25W109
+N25W110
+N25W111
+N25W112
+N25W113
+N26W077
+N26W078
+N26W079
+N26W080
+N26W081
+N26W082
+N26W083
+N26W098
+N26W099
+N26W100
+N26W101
+N26W102
+N26W103
+N26W104
+N26W105
+N26W106
+N26W107
+N26W108
+N26W109
+N26W110
+N26W112
+N26W113
+N26W114
+N26W115
+N27W078
+N27W079
+N27W081
+N27W082
+N27W083
+N27W097
+N27W098
+N27W099
+N27W100
+N27W101
+N27W102
+N27W103
+N27W104
+N27W105
+N27W106
+N27W107
+N27W108
+N27W109
+N27W110
+N27W111
+N27W112
+N27W113
+N27W114
+N27W115
+N27W116
+N28W081
+N28W082
+N28W083
+N28W090
+N28W096
+N28W097
+N28W098
+N28W099
+N28W100
+N28W101
+N28W102
+N28W103
+N28W104
+N28W105
+N28W106
+N28W107
+N28W108
+N28W109
+N28W110
+N28W111
+N28W112
+N28W113
+N28W114
+N28W115
+N28W116
+N28W119
+N29W081
+N29W082
+N29W083
+N29W084
+N29W085
+N29W086
+N29W089
+N29W090
+N29W091
+N29W092
+N29W093
+N29W094
+N29W095
+N29W096
+N29W097
+N29W098
+N29W099
+N29W100
+N29W101
+N29W102
+N29W103
+N29W104
+N29W105
+N29W106
+N29W107
+N29W108
+N29W109
+N29W110
+N29W111
+N29W112
+N29W113
+N29W114
+N29W115
+N29W116
+N29W119
+N30W082
+N30W083
+N30W084
+N30W085
+N30W086
+N30W087
+N30W088
+N30W089
+N30W090
+N30W091
+N30W092
+N30W093
+N30W094
+N30W095
+N30W096
+N30W097
+N30W098
+N30W099
+N30W100
+N30W101
+N30W102
+N30W103
+N30W104
+N30W105
+N30W106
+N30W107
+N30W108
+N30W109
+N30W110
+N30W111
+N30W112
+N30W113
+N30W114
+N30W115
+N30W116
+N30W117
+N31W081
+N31W082
+N31W083
+N31W084
+N31W085
+N31W086
+N31W087
+N31W088
+N31W089
+N31W090
+N31W091
+N31W092
+N31W093
+N31W094
+N31W095
+N31W096
+N31W097
+N31W098
+N31W099
+N31W100
+N31W101
+N31W102
+N31W103
+N31W104
+N31W105
+N31W106
+N31W107
+N31W108
+N31W109
+N31W110
+N31W111
+N31W112
+N31W113
+N31W114
+N31W115
+N31W116
+N31W117
+N32W065
+N32W080
+N32W081
+N32W082
+N32W083
+N32W084
+N32W085
+N32W086
+N32W087
+N32W088
+N32W089
+N32W090
+N32W091
+N32W092
+N32W093
+N32W094
+N32W095
+N32W096
+N32W097
+N32W098
+N32W099
+N32W100
+N32W101
+N32W102
+N32W103
+N32W104
+N32W105
+N32W106
+N32W107
+N32W108
+N32W109
+N32W110
+N32W111
+N32W112
+N32W113
+N32W114
+N32W115
+N32W116
+N32W117
+N32W118
+N32W119
+N33W078
+N33W079
+N33W080
+N33W081
+N33W082
+N33W083
+N33W084
+N33W085
+N33W086
+N33W087
+N33W088
+N33W089
+N33W090
+N33W091
+N33W092
+N33W093
+N33W094
+N33W095
+N33W096
+N33W097
+N33W098
+N33W099
+N33W100
+N33W101
+N33W102
+N33W103
+N33W104
+N33W105
+N33W106
+N33W107
+N33W108
+N33W109
+N33W110
+N33W111
+N33W112
+N33W113
+N33W114
+N33W115
+N33W116
+N33W117
+N33W118
+N33W119
+N33W120
+N33W121
+N34W077
+N34W078
+N34W079
+N34W080
+N34W081
+N34W082
+N34W083
+N34W084
+N34W085
+N34W086
+N34W087
+N34W088
+N34W089
+N34W090
+N34W091
+N34W092
+N34W093
+N34W094
+N34W095
+N34W096
+N34W097
+N34W098
+N34W099
+N34W100
+N34W101
+N34W102
+N34W103
+N34W104
+N34W105
+N34W106
+N34W107
+N34W108
+N34W109
+N34W110
+N34W111
+N34W112
+N34W113
+N34W114
+N34W115
+N34W116
+N34W117
+N34W118
+N34W119
+N34W120
+N34W121
+N35W076
+N35W077
+N35W078
+N35W079
+N35W080
+N35W081
+N35W082
+N35W083
+N35W084
+N35W085
+N35W086
+N35W087
+N35W088
+N35W089
+N35W090
+N35W091
+N35W092
+N35W093
+N35W094
+N35W095
+N35W096
+N35W097
+N35W098
+N35W099
+N35W100
+N35W101
+N35W102
+N35W103
+N35W104
+N35W105
+N35W106
+N35W107
+N35W108
+N35W109
+N35W110
+N35W111
+N35W112
+N35W113
+N35W114
+N35W115
+N35W116
+N35W117
+N35W118
+N35W119
+N35W120
+N35W121
+N35W122
+N36W076
+N36W077
+N36W078
+N36W079
+N36W080
+N36W081
+N36W082
+N36W083
+N36W084
+N36W085
+N36W086
+N36W087
+N36W088
+N36W089
+N36W090
+N36W091
+N36W092
+N36W093
+N36W094
+N36W095
+N36W096
+N36W097
+N36W098
+N36W099
+N36W100
+N36W101
+N36W102
+N36W103
+N36W104
+N36W105
+N36W106
+N36W107
+N36W108
+N36W109
+N36W110
+N36W111
+N36W112
+N36W113
+N36W114
+N36W115
+N36W116
+N36W117
+N36W118
+N36W119
+N36W120
+N36W121
+N36W122
+N36W123
+N37W076
+N37W077
+N37W078
+N37W079
+N37W080
+N37W081
+N37W082
+N37W083
+N37W084
+N37W085
+N37W086
+N37W087
+N37W088
+N37W089
+N37W090
+N37W091
+N37W092
+N37W093
+N37W094
+N37W095
+N37W096
+N37W097
+N37W098
+N37W099
+N37W100
+N37W101
+N37W102
+N37W103
+N37W104
+N37W105
+N37W106
+N37W107
+N37W108
+N37W109
+N37W110
+N37W111
+N37W112
+N37W113
+N37W114
+N37W115
+N37W116
+N37W117
+N37W118
+N37W119
+N37W120
+N37W121
+N37W122
+N37W123
+N37W124
+N38W075
+N38W076
+N38W077
+N38W078
+N38W079
+N38W080
+N38W081
+N38W082
+N38W083
+N38W084
+N38W085
+N38W086
+N38W087
+N38W088
+N38W089
+N38W090
+N38W091
+N38W092
+N38W093
+N38W094
+N38W095
+N38W096
+N38W097
+N38W098
+N38W099
+N38W100
+N38W101
+N38W102
+N38W103
+N38W104
+N38W105
+N38W106
+N38W107
+N38W108
+N38W109
+N38W110
+N38W111
+N38W112
+N38W113
+N38W114
+N38W115
+N38W116
+N38W117
+N38W118
+N38W119
+N38W120
+N38W121
+N38W122
+N38W123
+N38W124
+N39W075
+N39W076
+N39W077
+N39W078
+N39W079
+N39W080
+N39W081
+N39W082
+N39W083
+N39W084
+N39W085
+N39W086
+N39W087
+N39W088
+N39W089
+N39W090
+N39W091
+N39W092
+N39W093
+N39W094
+N39W095
+N39W096
+N39W097
+N39W098
+N39W099
+N39W100
+N39W101
+N39W102
+N39W103
+N39W104
+N39W105
+N39W106
+N39W107
+N39W108
+N39W109
+N39W110
+N39W111
+N39W112
+N39W113
+N39W114
+N39W115
+N39W116
+N39W117
+N39W118
+N39W119
+N39W120
+N39W121
+N39W122
+N39W123
+N39W124
+N39W125
+N40W073
+N40W074
+N40W075
+N40W076
+N40W077
+N40W078
+N40W079
+N40W080
+N40W081
+N40W082
+N40W083
+N40W084
+N40W085
+N40W086
+N40W087
+N40W088
+N40W089
+N40W090
+N40W091
+N40W092
+N40W093
+N40W094
+N40W095
+N40W096
+N40W097
+N40W098
+N40W099
+N40W100
+N40W101
+N40W102
+N40W103
+N40W104
+N40W105
+N40W106
+N40W107
+N40W108
+N40W109
+N40W110
+N40W111
+N40W112
+N40W113
+N40W114
+N40W115
+N40W116
+N40W117
+N40W118
+N40W119
+N40W120
+N40W121
+N40W122
+N40W123
+N40W124
+N40W125
+N41W070
+N41W071
+N41W072
+N41W073
+N41W074
+N41W075
+N41W076
+N41W077
+N41W078
+N41W079
+N41W080
+N41W081
+N41W082
+N41W083
+N41W084
+N41W085
+N41W086
+N41W087
+N41W088
+N41W089
+N41W090
+N41W091
+N41W092
+N41W093
+N41W094
+N41W095
+N41W096
+N41W097
+N41W098
+N41W099
+N41W100
+N41W101
+N41W102
+N41W103
+N41W104
+N41W105
+N41W106
+N41W107
+N41W108
+N41W109
+N41W110
+N41W111
+N41W112
+N41W113
+N41W114
+N41W115
+N41W116
+N41W117
+N41W118
+N41W119
+N41W120
+N41W121
+N41W122
+N41W123
+N41W124
+N41W125
+N42W071
+N42W072
+N42W073
+N42W074
+N42W075
+N42W076
+N42W077
+N42W078
+N42W079
+N42W080
+N42W081
+N42W082
+N42W083
+N42W084
+N42W085
+N42W086
+N42W087
+N42W088
+N42W089
+N42W090
+N42W091
+N42W092
+N42W093
+N42W094
+N42W095
+N42W096
+N42W097
+N42W098
+N42W099
+N42W100
+N42W101
+N42W102
+N42W103
+N42W104
+N42W105
+N42W106
+N42W107
+N42W108
+N42W109
+N42W110
+N42W111
+N42W112
+N42W113
+N42W114
+N42W115
+N42W116
+N42W117
+N42W118
+N42W119
+N42W120
+N42W121
+N42W122
+N42W123
+N42W124
+N42W125
+N43W060
+N43W061
+N43W065
+N43W066
+N43W067
+N43W069
+N43W070
+N43W071
+N43W072
+N43W073
+N43W074
+N43W075
+N43W076
+N43W077
+N43W078
+N43W079
+N43W080
+N43W081
+N43W082
+N43W083
+N43W084
+N43W085
+N43W086
+N43W087
+N43W088
+N43W089
+N43W090
+N43W091
+N43W092
+N43W093
+N43W094
+N43W095
+N43W096
+N43W097
+N43W098
+N43W099
+N43W100
+N43W101
+N43W102
+N43W103
+N43W104
+N43W105
+N43W106
+N43W107
+N43W108
+N43W109
+N43W110
+N43W111
+N43W112
+N43W113
+N43W114
+N43W115
+N43W116
+N43W117
+N43W118
+N43W119
+N43W120
+N43W121
+N43W122
+N43W123
+N43W124
+N43W125
+N44W060
+N44W062
+N44W063
+N44W064
+N44W065
+N44W066
+N44W067
+N44W068
+N44W069
+N44W070
+N44W071
+N44W072
+N44W073
+N44W074
+N44W075
+N44W076
+N44W077
+N44W078
+N44W079
+N44W080
+N44W081
+N44W082
+N44W083
+N44W084
+N44W085
+N44W086
+N44W087
+N44W088
+N44W089
+N44W090
+N44W091
+N44W092
+N44W093
+N44W094
+N44W095
+N44W096
+N44W097
+N44W098
+N44W099
+N44W100
+N44W101
+N44W102
+N44W103
+N44W104
+N44W105
+N44W106
+N44W107
+N44W108
+N44W109
+N44W110
+N44W111
+N44W112
+N44W113
+N44W114
+N44W115
+N44W116
+N44W117
+N44W118
+N44W119
+N44W120
+N44W121
+N44W122
+N44W123
+N44W124
+N44W125
+N45W060
+N45W061
+N45W062
+N45W063
+N45W064
+N45W065
+N45W066
+N45W067
+N45W068
+N45W069
+N45W070
+N45W071
+N45W072
+N45W073
+N45W074
+N45W075
+N45W076
+N45W077
+N45W078
+N45W079
+N45W080
+N45W081
+N45W082
+N45W083
+N45W084
+N45W085
+N45W086
+N45W087
+N45W088
+N45W089
+N45W090
+N45W091
+N45W092
+N45W093
+N45W094
+N45W095
+N45W096
+N45W097
+N45W098
+N45W099
+N45W100
+N45W101
+N45W102
+N45W103
+N45W104
+N45W105
+N45W106
+N45W107
+N45W108
+N45W109
+N45W110
+N45W111
+N45W112
+N45W113
+N45W114
+N45W115
+N45W116
+N45W117
+N45W118
+N45W119
+N45W120
+N45W121
+N45W122
+N45W123
+N45W124
+N45W125
+N46W053
+N46W054
+N46W055
+N46W056
+N46W057
+N46W060
+N46W061
+N46W062
+N46W063
+N46W064
+N46W065
+N46W066
+N46W067
+N46W068
+N46W069
+N46W070
+N46W071
+N46W072
+N46W073
+N46W074
+N46W075
+N46W076
+N46W077
+N46W078
+N46W079
+N46W080
+N46W081
+N46W082
+N46W083
+N46W084
+N46W085
+N46W086
+N46W087
+N46W088
+N46W089
+N46W090
+N46W091
+N46W092
+N46W093
+N46W094
+N46W095
+N46W096
+N46W097
+N46W098
+N46W099
+N46W100
+N46W101
+N46W102
+N46W103
+N46W104
+N46W105
+N46W106
+N46W107
+N46W108
+N46W109
+N46W110
+N46W111
+N46W112
+N46W113
+N46W114
+N46W115
+N46W116
+N46W117
+N46W118
+N46W119
+N46W120
+N46W121
+N46W122
+N46W123
+N46W124
+N46W125
+N47W053
+N47W054
+N47W055
+N47W056
+N47W057
+N47W058
+N47W059
+N47W060
+N47W061
+N47W062
+N47W063
+N47W064
+N47W065
+N47W066
+N47W067
+N47W068
+N47W069
+N47W070
+N47W071
+N47W072
+N47W073
+N47W074
+N47W075
+N47W076
+N47W077
+N47W078
+N47W079
+N47W080
+N47W081
+N47W082
+N47W083
+N47W084
+N47W085
+N47W086
+N47W088
+N47W089
+N47W090
+N47W091
+N47W092
+N47W093
+N47W094
+N47W095
+N47W096
+N47W097
+N47W098
+N47W099
+N47W100
+N47W101
+N47W102
+N47W103
+N47W104
+N47W105
+N47W106
+N47W107
+N47W108
+N47W109
+N47W110
+N47W111
+N47W112
+N47W113
+N47W114
+N47W115
+N47W116
+N47W117
+N47W118
+N47W119
+N47W120
+N47W121
+N47W122
+N47W123
+N47W124
+N47W125
+N48W053
+N48W054
+N48W055
+N48W056
+N48W057
+N48W058
+N48W059
+N48W060
+N48W065
+N48W066
+N48W067
+N48W068
+N48W069
+N48W070
+N48W071
+N48W072
+N48W073
+N48W074
+N48W075
+N48W076
+N48W077
+N48W078
+N48W079
+N48W080
+N48W081
+N48W082
+N48W083
+N48W084
+N48W085
+N48W086
+N48W087
+N48W088
+N48W089
+N48W090
+N48W091
+N48W092
+N48W093
+N48W094
+N48W095
+N48W096
+N48W097
+N48W098
+N48W099
+N48W100
+N48W101
+N48W102
+N48W103
+N48W104
+N48W105
+N48W106
+N48W107
+N48W108
+N48W109
+N48W110
+N48W111
+N48W112
+N48W113
+N48W114
+N48W115
+N48W116
+N48W117
+N48W118
+N48W119
+N48W120
+N48W121
+N48W122
+N48W123
+N48W124
+N48W125
+N48W126
+N49W054
+N49W055
+N49W056
+N49W057
+N49W058
+N49W059
+N49W062
+N49W063
+N49W064
+N49W065
+N49W066
+N49W067
+N49W068
+N49W069
+N49W070
+N49W071
+N49W072
+N49W073
+N49W074
+N49W075
+N49W076
+N49W077
+N49W078
+N49W079
+N49W080
+N49W081
+N49W082
+N49W083
+N49W084
+N49W085
+N49W086
+N49W087
+N49W088
+N49W089
+N49W090
+N49W091
+N49W092
+N49W093
+N49W094
+N49W095
+N49W096
+N49W097
+N49W098
+N49W099
+N49W100
+N49W101
+N49W102
+N49W103
+N49W104
+N49W105
+N49W106
+N49W107
+N49W108
+N49W109
+N49W110
+N49W111
+N49W112
+N49W113
+N49W114
+N49W115
+N49W116
+N49W117
+N49W118
+N49W119
+N49W120
+N49W121
+N49W122
+N49W123
+N49W124
+N49W125
+N49W126
+N49W127
+N49W128
+N50W056
+N50W057
+N50W058
+N50W059
+N50W060
+N50W061
+N50W062
+N50W063
+N50W064
+N50W065
+N50W066
+N50W067
+N50W068
+N50W069
+N50W070
+N50W071
+N50W072
+N50W073
+N50W074
+N50W075
+N50W076
+N50W077
+N50W078
+N50W079
+N50W080
+N50W081
+N50W082
+N50W083
+N50W084
+N50W085
+N50W086
+N50W087
+N50W088
+N50W089
+N50W090
+N50W091
+N50W092
+N50W093
+N50W094
+N50W095
+N50W096
+N50W097
+N50W098
+N50W099
+N50W100
+N50W101
+N50W102
+N50W103
+N50W104
+N50W105
+N50W106
+N50W107
+N50W108
+N50W109
+N50W110
+N50W111
+N50W112
+N50W113
+N50W114
+N50W115
+N50W116
+N50W117
+N50W118
+N50W119
+N50W120
+N50W121
+N50W122
+N50W123
+N50W124
+N50W125
+N50W126
+N50W127
+N50W128
+N50W129
+N50W130
+N51E177
+N51E178
+N51E179
+N51W056
+N51W057
+N51W058
+N51W059
+N51W060
+N51W061
+N51W062
+N51W063
+N51W064
+N51W065
+N51W066
+N51W067
+N51W068
+N51W069
+N51W070
+N51W071
+N51W072
+N51W073
+N51W074
+N51W075
+N51W076
+N51W077
+N51W078
+N51W079
+N51W080
+N51W081
+N51W082
+N51W083
+N51W084
+N51W085
+N51W086
+N51W087
+N51W088
+N51W089
+N51W090
+N51W091
+N51W092
+N51W093
+N51W094
+N51W095
+N51W096
+N51W097
+N51W098
+N51W099
+N51W100
+N51W101
+N51W102
+N51W103
+N51W104
+N51W105
+N51W106
+N51W107
+N51W108
+N51W109
+N51W110
+N51W111
+N51W112
+N51W113
+N51W114
+N51W115
+N51W116
+N51W117
+N51W118
+N51W119
+N51W120
+N51W121
+N51W122
+N51W123
+N51W124
+N51W125
+N51W126
+N51W127
+N51W128
+N51W129
+N51W131
+N51W132
+N51W176
+N51W177
+N51W178
+N51W179
+N51W180
+N52E172
+N52E173
+N52E174
+N52E175
+N52E177
+N52E178
+N52E179
+N52W056
+N52W057
+N52W058
+N52W059
+N52W060
+N52W061
+N52W062
+N52W063
+N52W064
+N52W065
+N52W066
+N52W067
+N52W068
+N52W069
+N52W070
+N52W071
+N52W072
+N52W073
+N52W074
+N52W075
+N52W076
+N52W077
+N52W078
+N52W079
+N52W080
+N52W081
+N52W082
+N52W083
+N52W084
+N52W085
+N52W086
+N52W087
+N52W088
+N52W089
+N52W090
+N52W091
+N52W092
+N52W093
+N52W094
+N52W095
+N52W096
+N52W097
+N52W098
+N52W099
+N52W100
+N52W101
+N52W102
+N52W103
+N52W104
+N52W105
+N52W106
+N52W107
+N52W108
+N52W109
+N52W110
+N52W111
+N52W112
+N52W113
+N52W114
+N52W115
+N52W116
+N52W117
+N52W118
+N52W119
+N52W120
+N52W121
+N52W122
+N52W123
+N52W124
+N52W125
+N52W126
+N52W127
+N52W128
+N52W129
+N52W130
+N52W131
+N52W132
+N52W133
+N52W169
+N52W170
+N52W171
+N52W172
+N52W173
+N52W174
+N52W175
+N52W176
+N52W177
+N53E172
+N53W056
+N53W057
+N53W058
+N53W059
+N53W060
+N53W061
+N53W062
+N53W063
+N53W064
+N53W065
+N53W066
+N53W067
+N53W068
+N53W069
+N53W070
+N53W071
+N53W072
+N53W073
+N53W074
+N53W075
+N53W076
+N53W077
+N53W078
+N53W079
+N53W080
+N53W081
+N53W082
+N53W083
+N53W084
+N53W085
+N53W086
+N53W087
+N53W088
+N53W089
+N53W090
+N53W091
+N53W092
+N53W093
+N53W094
+N53W095
+N53W096
+N53W097
+N53W098
+N53W099
+N53W100
+N53W101
+N53W102
+N53W103
+N53W104
+N53W105
+N53W106
+N53W107
+N53W108
+N53W109
+N53W110
+N53W111
+N53W112
+N53W113
+N53W114
+N53W115
+N53W116
+N53W117
+N53W118
+N53W119
+N53W120
+N53W121
+N53W122
+N53W123
+N53W124
+N53W125
+N53W126
+N53W127
+N53W128
+N53W129
+N53W130
+N53W131
+N53W132
+N53W133
+N53W134
+N53W167
+N53W168
+N53W169
+N53W170
+N54W057
+N54W058
+N54W059
+N54W060
+N54W061
+N54W062
+N54W063
+N54W064
+N54W065
+N54W066
+N54W067
+N54W068
+N54W069
+N54W070
+N54W071
+N54W072
+N54W073
+N54W074
+N54W075
+N54W076
+N54W077
+N54W078
+N54W079
+N54W080
+N54W081
+N54W082
+N54W083
+N54W084
+N54W085
+N54W086
+N54W087
+N54W088
+N54W089
+N54W090
+N54W091
+N54W092
+N54W093
+N54W094
+N54W095
+N54W096
+N54W097
+N54W098
+N54W099
+N54W100
+N54W101
+N54W102
+N54W103
+N54W104
+N54W105
+N54W106
+N54W107
+N54W108
+N54W109
+N54W110
+N54W111
+N54W112
+N54W113
+N54W114
+N54W115
+N54W116
+N54W117
+N54W118
+N54W119
+N54W120
+N54W121
+N54W122
+N54W123
+N54W124
+N54W125
+N54W126
+N54W127
+N54W128
+N54W129
+N54W130
+N54W131
+N54W132
+N54W133
+N54W134
+N54W160
+N54W161
+N54W162
+N54W163
+N54W164
+N54W165
+N54W166
+N54W167
+N55W070
+N55W071
+N55W072
+N55W112
+N55W113
+N55W124
+N55W125
+
diff --git a/tim/prune/function/srtm/gen/tiles3.txt b/tim/prune/function/srtm/gen/tiles3.txt
new file mode 100644 (file)
index 0000000..7334788
--- /dev/null
@@ -0,0 +1,1062 @@
+Australia
+S11E119
+S11E120
+S11E121
+S11E122
+S11E123
+S11E124
+S11E132
+S11E133
+S11E141
+S11E142
+S11E143
+S11E147
+S11E148
+S11E149
+S11E150
+S11E151
+S11E152
+S11E153
+S11E161
+S11E162
+S11E165
+S11E166
+S11E179
+S11W140
+S11W151
+S11W161
+S11W162
+S11W166
+S12E122
+S12E130
+S12E131
+S12E132
+S12E133
+S12E134
+S12E135
+S12E136
+S12E141
+S12E142
+S12E143
+S12E144
+S12E151
+S12E152
+S12E153
+S12E154
+S12E159
+S12E160
+S12E166
+S12E169
+S12E170
+S12W152
+S12W166
+S12W172
+S13E122
+S13E123
+S13E130
+S13E131
+S13E132
+S13E133
+S13E134
+S13E135
+S13E136
+S13E141
+S13E142
+S13E143
+S13E168
+S13E176
+S13E177
+S14E125
+S14E126
+S14E127
+S14E129
+S14E130
+S14E131
+S14E132
+S14E133
+S14E134
+S14E135
+S14E136
+S14E141
+S14E142
+S14E143
+S14E144
+S14E166
+S14E167
+S14W164
+S14W172
+S14W173
+S14W177
+S15E121
+S15E123
+S15E124
+S15E125
+S15E126
+S15E127
+S15E128
+S15E129
+S15E130
+S15E131
+S15E132
+S15E133
+S15E134
+S15E135
+S15E136
+S15E141
+S15E142
+S15E143
+S15E144
+S15E145
+S15E166
+S15E167
+S15E168
+S15W139
+S15W142
+S15W145
+S15W146
+S15W147
+S15W148
+S15W149
+S15W169
+S15W170
+S15W171
+S15W172
+S15W178
+S15W179
+S16E123
+S16E124
+S16E125
+S16E126
+S16E127
+S16E128
+S16E129
+S16E130
+S16E131
+S16E132
+S16E133
+S16E134
+S16E135
+S16E136
+S16E137
+S16E141
+S16E142
+S16E143
+S16E144
+S16E145
+S16E166
+S16E167
+S16E168
+S16W141
+S16W143
+S16W145
+S16W146
+S16W147
+S16W148
+S16W149
+S16W155
+S16W174
+S16W176
+S16W180
+S17E122
+S17E123
+S17E124
+S17E125
+S17E126
+S17E127
+S17E128
+S17E129
+S17E130
+S17E131
+S17E132
+S17E133
+S17E134
+S17E135
+S17E136
+S17E137
+S17E138
+S17E139
+S17E140
+S17E141
+S17E142
+S17E143
+S17E144
+S17E145
+S17E146
+S17E149
+S17E150
+S17E167
+S17E168
+S17E177
+S17E178
+S17E179
+S17W141
+S17W142
+S17W143
+S17W144
+S17W145
+S17W146
+S17W147
+S17W150
+S17W151
+S17W152
+S17W153
+S17W154
+S17W155
+S17W180
+S18E118
+S18E119
+S18E122
+S18E123
+S18E124
+S18E125
+S18E126
+S18E127
+S18E128
+S18E129
+S18E130
+S18E131
+S18E132
+S18E133
+S18E134
+S18E135
+S18E136
+S18E137
+S18E138
+S18E139
+S18E140
+S18E141
+S18E142
+S18E143
+S18E144
+S18E145
+S18E146
+S18E148
+S18E155
+S18E168
+S18E176
+S18E177
+S18E178
+S18E179
+S18W139
+S18W141
+S18W142
+S18W143
+S18W144
+S18W145
+S18W146
+S18W149
+S18W150
+S18W151
+S18W179
+S18W180
+S19E121
+S19E122
+S19E123
+S19E124
+S19E125
+S19E126
+S19E127
+S19E128
+S19E129
+S19E130
+S19E131
+S19E132
+S19E133
+S19E134
+S19E135
+S19E136
+S19E137
+S19E138
+S19E139
+S19E140
+S19E141
+S19E142
+S19E143
+S19E144
+S19E145
+S19E146
+S19E162
+S19E163
+S19E168
+S19E169
+S19E177
+S19E178
+S19E179
+S19W137
+S19W138
+S19W139
+S19W140
+S19W141
+S19W142
+S19W143
+S19W160
+S19W164
+S19W170
+S19W174
+S19W175
+S19W179
+S19W180
+S20E118
+S20E119
+S20E120
+S20E121
+S20E122
+S20E123
+S20E124
+S20E125
+S20E126
+S20E127
+S20E128
+S20E129
+S20E130
+S20E131
+S20E132
+S20E133
+S20E134
+S20E135
+S20E136
+S20E137
+S20E138
+S20E139
+S20E140
+S20E141
+S20E142
+S20E143
+S20E144
+S20E145
+S20E146
+S20E147
+S20E148
+S20E158
+S20E163
+S20E169
+S20E170
+S20E177
+S20E178
+S20E179
+S20W139
+S20W140
+S20W141
+S20W142
+S20W145
+S20W146
+S20W158
+S20W159
+S20W170
+S20W175
+S20W176
+S20W179
+S20W180
+S21E115
+S21E116
+S21E117
+S21E118
+S21E119
+S21E120
+S21E121
+S21E122
+S21E123
+S21E124
+S21E125
+S21E126
+S21E127
+S21E128
+S21E129
+S21E130
+S21E131
+S21E132
+S21E133
+S21E134
+S21E135
+S21E136
+S21E137
+S21E138
+S21E139
+S21E140
+S21E141
+S21E142
+S21E143
+S21E144
+S21E145
+S21E146
+S21E147
+S21E148
+S21E149
+S21E150
+S21E154
+S21E163
+S21E164
+S21E165
+S21E166
+S21E167
+S21E169
+S21W139
+S21W140
+S21W144
+S21W158
+S21W159
+S21W175
+S21W176
+S21W179
+S22E113
+S22E114
+S22E115
+S22E116
+S22E117
+S22E118
+S22E119
+S22E120
+S22E121
+S22E122
+S22E123
+S22E124
+S22E125
+S22E126
+S22E127
+S22E128
+S22E129
+S22E130
+S22E131
+S22E132
+S22E133
+S22E134
+S22E135
+S22E136
+S22E137
+S22E138
+S22E139
+S22E140
+S22E141
+S22E142
+S22E143
+S22E144
+S22E145
+S22E146
+S22E147
+S22E148
+S22E149
+S22E150
+S22E151
+S22E152
+S22E153
+S22E154
+S22E155
+S22E158
+S22E164
+S22E165
+S22E166
+S22E167
+S22E168
+S22W136
+S22W137
+S22W139
+S22W140
+S22W141
+S22W155
+S22W158
+S22W160
+S22W175
+S22W176
+S22W179
+S23E113
+S23E114
+S23E115
+S23E116
+S23E117
+S23E118
+S23E119
+S23E120
+S23E121
+S23E122
+S23E123
+S23E124
+S23E125
+S23E126
+S23E127
+S23E128
+S23E129
+S23E130
+S23E131
+S23E132
+S23E133
+S23E134
+S23E135
+S23E136
+S23E137
+S23E138
+S23E139
+S23E140
+S23E141
+S23E142
+S23E143
+S23E144
+S23E145
+S23E146
+S23E147
+S23E148
+S23E149
+S23E150
+S23E152
+S23E155
+S23E165
+S23E166
+S23E167
+S23E168
+S23E171
+S23E172
+S23W135
+S23W137
+S23W139
+S23W152
+S23W153
+S23W177
+S24E113
+S24E114
+S24E115
+S24E116
+S24E117
+S24E118
+S24E119
+S24E120
+S24E121
+S24E122
+S24E123
+S24E124
+S24E125
+S24E126
+S24E127
+S24E128
+S24E129
+S24E130
+S24E131
+S24E132
+S24E133
+S24E134
+S24E135
+S24E136
+S24E137
+S24E138
+S24E139
+S24E140
+S24E141
+S24E142
+S24E143
+S24E144
+S24E145
+S24E146
+S24E147
+S24E148
+S24E149
+S24E150
+S24E151
+S24E152
+S24E155
+S24W131
+S24W135
+S24W136
+S24W138
+S24W148
+S24W150
+S25E113
+S25E114
+S25E115
+S25E116
+S25E117
+S25E118
+S25E119
+S25E120
+S25E121
+S25E122
+S25E123
+S25E124
+S25E125
+S25E126
+S25E127
+S25E128
+S25E129
+S25E130
+S25E131
+S25E132
+S25E133
+S25E134
+S25E135
+S25E136
+S25E137
+S25E138
+S25E139
+S25E140
+S25E141
+S25E142
+S25E143
+S25E144
+S25E145
+S25E146
+S25E147
+S25E148
+S25E149
+S25E150
+S25E151
+S25E152
+S25E153
+S25W125
+S25W129
+S26E112
+S26E113
+S26E114
+S26E115
+S26E116
+S26E117
+S26E118
+S26E119
+S26E120
+S26E121
+S26E122
+S26E123
+S26E124
+S26E125
+S26E126
+S26E127
+S26E128
+S26E129
+S26E130
+S26E131
+S26E132
+S26E133
+S26E134
+S26E135
+S26E136
+S26E137
+S26E138
+S26E139
+S26E140
+S26E141
+S26E142
+S26E143
+S26E144
+S26E145
+S26E146
+S26E147
+S26E148
+S26E149
+S26E150
+S26E151
+S26E152
+S26E153
+S26W131
+S27E113
+S27E114
+S27E115
+S27E116
+S27E117
+S27E118
+S27E119
+S27E120
+S27E121
+S27E122
+S27E123
+S27E124
+S27E125
+S27E126
+S27E127
+S27E128
+S27E129
+S27E130
+S27E131
+S27E132
+S27E133
+S27E134
+S27E135
+S27E136
+S27E137
+S27E138
+S27E139
+S27E140
+S27E141
+S27E142
+S27E143
+S27E144
+S27E145
+S27E146
+S27E147
+S27E148
+S27E149
+S27E150
+S27E151
+S27E152
+S27E153
+S27W106
+S28E113
+S28E114
+S28E115
+S28E116
+S28E117
+S28E118
+S28E119
+S28E120
+S28E121
+S28E122
+S28E123
+S28E124
+S28E125
+S28E126
+S28E127
+S28E128
+S28E129
+S28E130
+S28E131
+S28E132
+S28E133
+S28E134
+S28E135
+S28E136
+S28E137
+S28E138
+S28E139
+S28E140
+S28E141
+S28E142
+S28E143
+S28E144
+S28E145
+S28E146
+S28E147
+S28E148
+S28E149
+S28E150
+S28E151
+S28E152
+S28E153
+S28W110
+S28W144
+S28W145
+S29E113
+S29E114
+S29E115
+S29E116
+S29E117
+S29E118
+S29E119
+S29E120
+S29E121
+S29E122
+S29E123
+S29E124
+S29E125
+S29E126
+S29E127
+S29E128
+S29E129
+S29E130
+S29E131
+S29E132
+S29E133
+S29E134
+S29E135
+S29E136
+S29E137
+S29E138
+S29E139
+S29E140
+S29E141
+S29E142
+S29E143
+S29E144
+S29E145
+S29E146
+S29E147
+S29E148
+S29E149
+S29E150
+S29E151
+S29E152
+S29E153
+S30E114
+S30E115
+S30E116
+S30E117
+S30E118
+S30E119
+S30E120
+S30E121
+S30E122
+S30E123
+S30E124
+S30E125
+S30E126
+S30E127
+S30E128
+S30E129
+S30E130
+S30E131
+S30E132
+S30E133
+S30E134
+S30E135
+S30E136
+S30E137
+S30E138
+S30E139
+S30E140
+S30E141
+S30E142
+S30E143
+S30E144
+S30E145
+S30E146
+S30E147
+S30E148
+S30E149
+S30E150
+S30E151
+S30E152
+S30E153
+S31E114
+S31E115
+S31E116
+S31E117
+S31E118
+S31E119
+S31E120
+S31E121
+S31E122
+S31E123
+S31E124
+S31E125
+S31E126
+S31E127
+S31E128
+S31E129
+S31E130
+S31E131
+S31E132
+S31E133
+S31E134
+S31E135
+S31E136
+S31E137
+S31E138
+S31E139
+S31E140
+S31E141
+S31E142
+S31E143
+S31E144
+S31E145
+S31E146
+S31E147
+S31E148
+S31E149
+S31E150
+S31E151
+S31E152
+S31E153
+S32E115
+S32E116
+S32E117
+S32E118
+S32E119
+S32E120
+S32E121
+S32E122
+S32E123
+S32E124
+S32E125
+S32E126
+S32E127
+S32E128
+S32E129
+S32E130
+S32E131
+S32E132
+S32E133
+S32E134
+S32E135
+S32E136
+S32E137
+S32E138
+S32E139
+S32E140
+S32E141
+S32E142
+S32E143
+S32E144
+S32E145
+S32E146
+S32E147
+S32E148
+S32E149
+S32E150
+S32E151
+S32E152
+S32E153
+S32E159
+S33E115
+S33E116
+S33E117
+S33E118
+S33E119
+S33E120
+S33E121
+S33E122
+S33E123
+S33E124
+S33E125
+S33E126
+S33E127
+S33E128
+S33E132
+S33E133
+S33E134
+S33E135
+S33E136
+S33E137
+S33E138
+S33E139
+S33E140
+S33E141
+S33E142
+S33E143
+S33E144
+S33E145
+S33E146
+S33E147
+S33E148
+S33E149
+S33E150
+S33E151
+S33E152
+S34E114
+S34E115
+S34E116
+S34E117
+S34E118
+S34E119
+S34E120
+S34E121
+S34E122
+S34E123
+S34E124
+S34E134
+S34E135
+S34E136
+S34E137
+S34E138
+S34E139
+S34E140
+S34E141
+S34E142
+S34E143
+S34E144
+S34E145
+S34E146
+S34E147
+S34E148
+S34E149
+S34E150
+S34E151
+S35E114
+S35E115
+S35E116
+S35E117
+S35E118
+S35E119
+S35E120
+S35E121
+S35E122
+S35E123
+S35E134
+S35E135
+S35E136
+S35E137
+S35E138
+S35E139
+S35E140
+S35E141
+S35E142
+S35E143
+S35E144
+S35E145
+S35E146
+S35E147
+S35E148
+S35E149
+S35E150
+S35E151
+S36E116
+S36E117
+S36E118
+S36E135
+S36E136
+S36E137
+S36E138
+S36E139
+S36E140
+S36E141
+S36E142
+S36E143
+S36E144
+S36E145
+S36E146
+S36E147
+S36E148
+S36E149
+S36E150
+S37E136
+S37E137
+S37E139
+S37E140
+S37E141
+S37E142
+S37E143
+S37E144
+S37E145
+S37E146
+S37E147
+S37E148
+S37E149
+S37E150
+S38E139
+S38E140
+S38E141
+S38E142
+S38E143
+S38E144
+S38E145
+S38E146
+S38E147
+S38E148
+S38E149
+S38E150
+S39E140
+S39E141
+S39E142
+S39E143
+S39E144
+S39E145
+S39E146
+S39E147
+S40E143
+S40E144
+S40E146
+S40E147
+S40E148
+S41E143
+S41E144
+S41E145
+S41E146
+S41E147
+S41E148
+S42E144
+S42E145
+S42E146
+S42E147
+S42E148
+S43E145
+S43E146
+S43E147
+S43E148
+S44E145
+S44E146
+S44E147
+S44E148
+
diff --git a/tim/prune/function/srtm/gen/tiles4.txt b/tim/prune/function/srtm/gen/tiles4.txt
new file mode 100644 (file)
index 0000000..3894bcd
--- /dev/null
@@ -0,0 +1,143 @@
+Islands
+N16W170
+N18W156
+N19W155
+N19W156
+N19W157
+N20W156
+N20W157
+N20W158
+N21W157
+N21W158
+N21W159
+N21W160
+N21W161
+N22W160
+N22W161
+N23W162
+N23W165
+N23W167
+N24W168
+N25W168
+N25W172
+N26W174
+N27W176
+N28W178
+N28W179
+S08W015
+S16W006
+S17W006
+S21W029
+S21W030
+S29E167
+S30E167
+S30W178
+S31W179
+S32W179
+S35E172
+S35E173
+S36E173
+S36E174
+S36E175
+S37E173
+S37E174
+S37E175
+S37E176
+S38E077
+S38E174
+S38E175
+S38E176
+S38E177
+S38E178
+S38W013
+S39E077
+S39E174
+S39E175
+S39E176
+S39E177
+S39E178
+S40E173
+S40E174
+S40E175
+S40E176
+S40E177
+S40E178
+S41E172
+S41E173
+S41E174
+S41E175
+S41E176
+S41W010
+S41W011
+S42E171
+S42E172
+S42E173
+S42E174
+S42E175
+S42E176
+S43E170
+S43E171
+S43E172
+S43E173
+S43E174
+S44E168
+S44E169
+S44E170
+S44E171
+S44E172
+S44E173
+S44W176
+S44W177
+S45E167
+S45E168
+S45E169
+S45E170
+S45E171
+S45W176
+S45W177
+S46E050
+S46E166
+S46E167
+S46E168
+S46E169
+S46E170
+S46E171
+S47E037
+S47E038
+S47E050
+S47E051
+S47E052
+S47E166
+S47E167
+S47E168
+S47E169
+S47E170
+S48E167
+S48E168
+S48E179
+S49E068
+S49E069
+S49E166
+S50E068
+S50E069
+S50E070
+S50E178
+S51E068
+S51E165
+S51E166
+S53E073
+S53E168
+S53E169
+S54E072
+S54E073
+S54W038
+S54W039
+S55E003
+S55E158
+S55W036
+S55W037
+S55W038
+S55W039
+S56E158
+S56W035
+
diff --git a/tim/prune/function/srtm/gen/tiles5.txt b/tim/prune/function/srtm/gen/tiles5.txt
new file mode 100644 (file)
index 0000000..6e4deb7
--- /dev/null
@@ -0,0 +1,1809 @@
+South_America
+N00W050
+N00W051
+N00W052
+N00W053
+N00W054
+N00W055
+N00W056
+N00W057
+N00W058
+N00W059
+N00W060
+N00W061
+N00W062
+N00W063
+N00W064
+N00W065
+N00W066
+N00W067
+N00W068
+N00W069
+N00W070
+N00W071
+N00W072
+N00W073
+N00W074
+N00W075
+N00W076
+N00W077
+N00W078
+N00W079
+N00W080
+N00W081
+N00W090
+N00W091
+N00W092
+N01W050
+N01W051
+N01W052
+N01W053
+N01W054
+N01W055
+N01W056
+N01W057
+N01W058
+N01W059
+N01W060
+N01W061
+N01W062
+N01W063
+N01W064
+N01W065
+N01W066
+N01W067
+N01W068
+N01W069
+N01W070
+N01W071
+N01W072
+N01W073
+N01W074
+N01W075
+N01W076
+N01W077
+N01W078
+N01W079
+N01W080
+N01W092
+N02W051
+N02W052
+N02W053
+N02W054
+N02W055
+N02W056
+N02W057
+N02W058
+N02W059
+N02W060
+N02W061
+N02W062
+N02W063
+N02W064
+N02W065
+N02W066
+N02W067
+N02W068
+N02W069
+N02W070
+N02W071
+N02W072
+N02W073
+N02W074
+N02W075
+N02W076
+N02W077
+N02W078
+N02W079
+N03W051
+N03W052
+N03W053
+N03W054
+N03W055
+N03W056
+N03W057
+N03W058
+N03W059
+N03W060
+N03W061
+N03W062
+N03W063
+N03W064
+N03W065
+N03W066
+N03W067
+N03W068
+N03W069
+N03W070
+N03W071
+N03W072
+N03W073
+N03W074
+N03W075
+N03W076
+N03W077
+N03W078
+N03W079
+N03W082
+N04W052
+N04W053
+N04W054
+N04W055
+N04W056
+N04W057
+N04W058
+N04W059
+N04W060
+N04W061
+N04W062
+N04W063
+N04W064
+N04W065
+N04W066
+N04W067
+N04W068
+N04W069
+N04W070
+N04W071
+N04W072
+N04W073
+N04W074
+N04W075
+N04W076
+N04W077
+N04W078
+N04W082
+N05W053
+N05W054
+N05W055
+N05W056
+N05W057
+N05W058
+N05W059
+N05W060
+N05W061
+N05W062
+N05W063
+N05W064
+N05W065
+N05W066
+N05W067
+N05W068
+N05W069
+N05W070
+N05W071
+N05W072
+N05W073
+N05W074
+N05W075
+N05W076
+N05W077
+N05W078
+N05W088
+N06W056
+N06W057
+N06W058
+N06W059
+N06W060
+N06W061
+N06W062
+N06W063
+N06W064
+N06W065
+N06W066
+N06W067
+N06W068
+N06W069
+N06W070
+N06W071
+N06W072
+N06W073
+N06W074
+N06W075
+N06W076
+N06W077
+N06W078
+N07W059
+N07W060
+N07W061
+N07W062
+N07W063
+N07W064
+N07W065
+N07W066
+N07W067
+N07W068
+N07W069
+N07W070
+N07W071
+N07W072
+N07W073
+N07W074
+N07W075
+N07W076
+N07W077
+N07W078
+N07W079
+N07W080
+N07W081
+N07W082
+N07W083
+N08W060
+N08W061
+N08W062
+N08W063
+N08W064
+N08W065
+N08W066
+N08W067
+N08W068
+N08W069
+N08W070
+N08W071
+N08W072
+N08W073
+N08W074
+N08W075
+N08W076
+N08W077
+N08W078
+N08W079
+N08W080
+N08W081
+N08W082
+N08W083
+N08W084
+N09W061
+N09W062
+N09W063
+N09W064
+N09W065
+N09W066
+N09W067
+N09W068
+N09W069
+N09W070
+N09W071
+N09W072
+N09W073
+N09W074
+N09W075
+N09W076
+N09W077
+N09W078
+N09W079
+N09W080
+N09W081
+N09W082
+N09W083
+N09W084
+N09W085
+N09W086
+N10W061
+N10W062
+N10W063
+N10W064
+N10W065
+N10W066
+N10W067
+N10W068
+N10W069
+N10W070
+N10W071
+N10W072
+N10W073
+N10W074
+N10W075
+N10W076
+N10W084
+N10W085
+N10W086
+N11W061
+N11W062
+N11W064
+N11W065
+N11W067
+N11W068
+N11W069
+N11W070
+N11W071
+N11W072
+N11W073
+N11W074
+N11W075
+N11W084
+N11W085
+N11W086
+N11W087
+N12W062
+N12W069
+N12W070
+N12W071
+N12W072
+N12W073
+N12W082
+N12W083
+N12W084
+N12W085
+N12W086
+N12W087
+N12W088
+N13W060
+N13W061
+N13W062
+N13W081
+N13W082
+N13W084
+N13W085
+N13W086
+N13W087
+N13W088
+N13W089
+N13W090
+N13W091
+N13W092
+N14W061
+N14W062
+N14W081
+N14W083
+N14W084
+N14W085
+N14W086
+N14W087
+N14W088
+N14W089
+N14W090
+N14W091
+N14W092
+N14W093
+S01W047
+S01W048
+S01W049
+S01W050
+S01W051
+S01W052
+S01W053
+S01W054
+S01W055
+S01W056
+S01W057
+S01W058
+S01W059
+S01W060
+S01W061
+S01W062
+S01W063
+S01W064
+S01W065
+S01W066
+S01W067
+S01W068
+S01W069
+S01W070
+S01W071
+S01W072
+S01W073
+S01W074
+S01W075
+S01W076
+S01W077
+S01W078
+S01W079
+S01W080
+S01W081
+S01W090
+S01W091
+S01W092
+S02W045
+S02W046
+S02W047
+S02W048
+S02W049
+S02W050
+S02W051
+S02W052
+S02W053
+S02W054
+S02W055
+S02W056
+S02W057
+S02W058
+S02W059
+S02W060
+S02W061
+S02W062
+S02W063
+S02W064
+S02W065
+S02W066
+S02W067
+S02W068
+S02W069
+S02W070
+S02W071
+S02W072
+S02W073
+S02W074
+S02W075
+S02W076
+S02W077
+S02W078
+S02W079
+S02W080
+S02W081
+S02W082
+S02W090
+S02W091
+S02W092
+S03W040
+S03W041
+S03W042
+S03W043
+S03W044
+S03W045
+S03W046
+S03W047
+S03W048
+S03W049
+S03W050
+S03W051
+S03W052
+S03W053
+S03W054
+S03W055
+S03W056
+S03W057
+S03W058
+S03W059
+S03W060
+S03W061
+S03W062
+S03W063
+S03W064
+S03W065
+S03W066
+S03W067
+S03W068
+S03W069
+S03W070
+S03W071
+S03W072
+S03W073
+S03W074
+S03W075
+S03W076
+S03W077
+S03W078
+S03W079
+S03W080
+S03W081
+S03W082
+S04W033
+S04W034
+S04W039
+S04W040
+S04W041
+S04W042
+S04W043
+S04W044
+S04W045
+S04W046
+S04W047
+S04W048
+S04W049
+S04W050
+S04W051
+S04W052
+S04W053
+S04W054
+S04W055
+S04W056
+S04W057
+S04W058
+S04W059
+S04W060
+S04W061
+S04W062
+S04W063
+S04W064
+S04W065
+S04W066
+S04W067
+S04W068
+S04W069
+S04W070
+S04W071
+S04W072
+S04W073
+S04W074
+S04W075
+S04W076
+S04W077
+S04W078
+S04W079
+S04W080
+S04W081
+S05W037
+S05W038
+S05W039
+S05W040
+S05W041
+S05W042
+S05W043
+S05W044
+S05W045
+S05W046
+S05W047
+S05W048
+S05W049
+S05W050
+S05W051
+S05W052
+S05W053
+S05W054
+S05W055
+S05W056
+S05W057
+S05W058
+S05W059
+S05W060
+S05W061
+S05W062
+S05W063
+S05W064
+S05W065
+S05W066
+S05W067
+S05W068
+S05W069
+S05W070
+S05W071
+S05W072
+S05W073
+S05W074
+S05W075
+S05W076
+S05W077
+S05W078
+S05W079
+S05W080
+S05W081
+S05W082
+S06W036
+S06W037
+S06W038
+S06W039
+S06W040
+S06W041
+S06W042
+S06W043
+S06W044
+S06W045
+S06W046
+S06W047
+S06W048
+S06W049
+S06W050
+S06W051
+S06W052
+S06W053
+S06W054
+S06W055
+S06W056
+S06W057
+S06W058
+S06W059
+S06W060
+S06W061
+S06W062
+S06W063
+S06W064
+S06W065
+S06W066
+S06W067
+S06W068
+S06W069
+S06W070
+S06W071
+S06W072
+S06W073
+S06W074
+S06W075
+S06W076
+S06W077
+S06W078
+S06W079
+S06W080
+S06W081
+S06W082
+S07W035
+S07W036
+S07W037
+S07W038
+S07W039
+S07W040
+S07W041
+S07W042
+S07W043
+S07W044
+S07W045
+S07W046
+S07W047
+S07W048
+S07W049
+S07W050
+S07W051
+S07W052
+S07W053
+S07W054
+S07W055
+S07W056
+S07W057
+S07W058
+S07W059
+S07W060
+S07W061
+S07W062
+S07W063
+S07W064
+S07W065
+S07W066
+S07W067
+S07W068
+S07W069
+S07W070
+S07W071
+S07W072
+S07W073
+S07W074
+S07W075
+S07W076
+S07W077
+S07W078
+S07W079
+S07W080
+S07W081
+S07W082
+S08W035
+S08W036
+S08W037
+S08W038
+S08W039
+S08W040
+S08W041
+S08W042
+S08W043
+S08W044
+S08W045
+S08W046
+S08W047
+S08W048
+S08W049
+S08W050
+S08W051
+S08W052
+S08W053
+S08W054
+S08W055
+S08W056
+S08W057
+S08W058
+S08W059
+S08W060
+S08W061
+S08W062
+S08W063
+S08W064
+S08W065
+S08W066
+S08W067
+S08W068
+S08W069
+S08W070
+S08W071
+S08W072
+S08W073
+S08W074
+S08W075
+S08W076
+S08W077
+S08W078
+S08W079
+S08W080
+S09W035
+S09W036
+S09W037
+S09W038
+S09W039
+S09W040
+S09W041
+S09W042
+S09W043
+S09W044
+S09W045
+S09W046
+S09W047
+S09W048
+S09W049
+S09W050
+S09W051
+S09W052
+S09W053
+S09W054
+S09W055
+S09W056
+S09W057
+S09W058
+S09W059
+S09W060
+S09W061
+S09W062
+S09W063
+S09W064
+S09W065
+S09W066
+S09W067
+S09W068
+S09W069
+S09W070
+S09W071
+S09W072
+S09W073
+S09W074
+S09W075
+S09W076
+S09W077
+S09W078
+S09W079
+S09W080
+S10W036
+S10W037
+S10W038
+S10W039
+S10W040
+S10W041
+S10W042
+S10W043
+S10W044
+S10W045
+S10W046
+S10W047
+S10W048
+S10W049
+S10W050
+S10W051
+S10W052
+S10W053
+S10W054
+S10W055
+S10W056
+S10W057
+S10W058
+S10W059
+S10W060
+S10W061
+S10W062
+S10W063
+S10W064
+S10W065
+S10W066
+S10W067
+S10W068
+S10W069
+S10W070
+S10W071
+S10W072
+S10W073
+S10W074
+S10W075
+S10W076
+S10W077
+S10W078
+S10W079
+S11W037
+S11W038
+S11W039
+S11W040
+S11W041
+S11W042
+S11W043
+S11W044
+S11W045
+S11W046
+S11W047
+S11W048
+S11W049
+S11W050
+S11W051
+S11W052
+S11W053
+S11W054
+S11W055
+S11W056
+S11W057
+S11W058
+S11W059
+S11W060
+S11W061
+S11W062
+S11W063
+S11W064
+S11W065
+S11W066
+S11W067
+S11W068
+S11W069
+S11W070
+S11W071
+S11W072
+S11W073
+S11W074
+S11W075
+S11W076
+S11W077
+S11W078
+S11W079
+S12W038
+S12W039
+S12W040
+S12W041
+S12W042
+S12W043
+S12W044
+S12W045
+S12W046
+S12W047
+S12W048
+S12W049
+S12W050
+S12W051
+S12W052
+S12W053
+S12W054
+S12W055
+S12W056
+S12W057
+S12W058
+S12W059
+S12W060
+S12W061
+S12W062
+S12W063
+S12W064
+S12W065
+S12W066
+S12W067
+S12W068
+S12W069
+S12W070
+S12W071
+S12W072
+S12W073
+S12W074
+S12W075
+S12W076
+S12W077
+S12W078
+S13W038
+S13W039
+S13W040
+S13W041
+S13W042
+S13W043
+S13W044
+S13W045
+S13W046
+S13W047
+S13W048
+S13W049
+S13W050
+S13W051
+S13W052
+S13W053
+S13W054
+S13W055
+S13W056
+S13W057
+S13W058
+S13W059
+S13W060
+S13W061
+S13W062
+S13W063
+S13W064
+S13W065
+S13W066
+S13W067
+S13W068
+S13W069
+S13W070
+S13W071
+S13W072
+S13W073
+S13W074
+S13W075
+S13W076
+S13W077
+S13W078
+S14W039
+S14W040
+S14W041
+S14W042
+S14W043
+S14W044
+S14W045
+S14W046
+S14W047
+S14W048
+S14W049
+S14W050
+S14W051
+S14W052
+S14W053
+S14W054
+S14W055
+S14W056
+S14W057
+S14W058
+S14W059
+S14W060
+S14W061
+S14W062
+S14W063
+S14W064
+S14W065
+S14W066
+S14W067
+S14W068
+S14W069
+S14W070
+S14W071
+S14W072
+S14W073
+S14W074
+S14W075
+S14W076
+S14W077
+S15W039
+S15W040
+S15W041
+S15W042
+S15W043
+S15W044
+S15W045
+S15W046
+S15W047
+S15W048
+S15W049
+S15W050
+S15W051
+S15W052
+S15W053
+S15W054
+S15W055
+S15W056
+S15W057
+S15W058
+S15W059
+S15W060
+S15W061
+S15W062
+S15W063
+S15W064
+S15W065
+S15W066
+S15W067
+S15W068
+S15W069
+S15W070
+S15W071
+S15W072
+S15W073
+S15W074
+S15W075
+S15W076
+S15W077
+S16W039
+S16W040
+S16W041
+S16W042
+S16W043
+S16W044
+S16W045
+S16W046
+S16W047
+S16W048
+S16W049
+S16W050
+S16W051
+S16W052
+S16W053
+S16W054
+S16W055
+S16W056
+S16W057
+S16W058
+S16W059
+S16W060
+S16W061
+S16W062
+S16W063
+S16W064
+S16W065
+S16W066
+S16W067
+S16W068
+S16W069
+S16W070
+S16W071
+S16W072
+S16W073
+S16W074
+S16W075
+S16W076
+S17W039
+S17W040
+S17W041
+S17W042
+S17W043
+S17W044
+S17W045
+S17W046
+S17W047
+S17W048
+S17W049
+S17W050
+S17W051
+S17W052
+S17W053
+S17W054
+S17W055
+S17W056
+S17W057
+S17W058
+S17W059
+S17W060
+S17W061
+S17W062
+S17W063
+S17W064
+S17W065
+S17W066
+S17W067
+S17W068
+S17W070
+S17W071
+S17W072
+S17W073
+S17W074
+S17W075
+S18W039
+S18W040
+S18W041
+S18W042
+S18W043
+S18W044
+S18W045
+S18W046
+S18W047
+S18W048
+S18W049
+S18W050
+S18W051
+S18W052
+S18W053
+S18W054
+S18W055
+S18W056
+S18W057
+S18W058
+S18W059
+S18W060
+S18W061
+S18W062
+S18W063
+S18W064
+S18W065
+S18W066
+S18W067
+S18W068
+S18W069
+S18W070
+S18W071
+S18W072
+S18W073
+S19W040
+S19W041
+S19W042
+S19W043
+S19W044
+S19W045
+S19W046
+S19W047
+S19W048
+S19W049
+S19W050
+S19W051
+S19W052
+S19W053
+S19W054
+S19W055
+S19W056
+S19W057
+S19W058
+S19W059
+S19W060
+S19W061
+S19W062
+S19W063
+S19W064
+S19W065
+S19W066
+S19W067
+S19W068
+S19W069
+S19W070
+S19W071
+S20W040
+S20W041
+S20W042
+S20W043
+S20W044
+S20W045
+S20W046
+S20W047
+S20W048
+S20W049
+S20W050
+S20W051
+S20W052
+S20W053
+S20W054
+S20W055
+S20W056
+S20W057
+S20W058
+S20W059
+S20W060
+S20W061
+S20W062
+S20W063
+S20W064
+S20W065
+S20W066
+S20W067
+S20W068
+S20W069
+S20W070
+S20W071
+S21W041
+S21W042
+S21W043
+S21W044
+S21W045
+S21W046
+S21W047
+S21W048
+S21W049
+S21W050
+S21W051
+S21W052
+S21W053
+S21W054
+S21W055
+S21W056
+S21W057
+S21W058
+S21W059
+S21W060
+S21W061
+S21W062
+S21W063
+S21W064
+S21W065
+S21W066
+S21W067
+S21W068
+S21W069
+S21W070
+S21W071
+S22W041
+S22W042
+S22W043
+S22W044
+S22W045
+S22W046
+S22W047
+S22W048
+S22W049
+S22W050
+S22W051
+S22W052
+S22W053
+S22W054
+S22W055
+S22W056
+S22W057
+S22W058
+S22W059
+S22W060
+S22W061
+S22W062
+S22W063
+S22W064
+S22W065
+S22W066
+S22W067
+S22W068
+S22W069
+S22W070
+S22W071
+S23W041
+S23W042
+S23W043
+S23W044
+S23W045
+S23W046
+S23W047
+S23W048
+S23W049
+S23W050
+S23W051
+S23W052
+S23W053
+S23W054
+S23W055
+S23W056
+S23W057
+S23W058
+S23W059
+S23W060
+S23W061
+S23W062
+S23W063
+S23W064
+S23W065
+S23W066
+S23W067
+S23W068
+S23W069
+S23W070
+S23W071
+S24W042
+S24W043
+S24W044
+S24W045
+S24W046
+S24W047
+S24W048
+S24W049
+S24W050
+S24W051
+S24W052
+S24W053
+S24W054
+S24W055
+S24W056
+S24W057
+S24W058
+S24W059
+S24W060
+S24W061
+S24W062
+S24W063
+S24W064
+S24W065
+S24W066
+S24W067
+S24W068
+S24W069
+S24W070
+S24W071
+S25W046
+S25W047
+S25W048
+S25W049
+S25W050
+S25W051
+S25W052
+S25W053
+S25W054
+S25W055
+S25W056
+S25W057
+S25W058
+S25W059
+S25W060
+S25W061
+S25W062
+S25W063
+S25W064
+S25W065
+S25W066
+S25W067
+S25W068
+S25W069
+S25W070
+S25W071
+S26W048
+S26W049
+S26W050
+S26W051
+S26W052
+S26W053
+S26W054
+S26W055
+S26W056
+S26W057
+S26W058
+S26W059
+S26W060
+S26W061
+S26W062
+S26W063
+S26W064
+S26W065
+S26W066
+S26W067
+S26W068
+S26W069
+S26W070
+S26W071
+S27W049
+S27W050
+S27W051
+S27W052
+S27W053
+S27W054
+S27W055
+S27W056
+S27W057
+S27W058
+S27W059
+S27W060
+S27W061
+S27W062
+S27W063
+S27W064
+S27W065
+S27W066
+S27W067
+S27W068
+S27W069
+S27W070
+S27W071
+S27W080
+S27W081
+S28W049
+S28W050
+S28W051
+S28W052
+S28W053
+S28W054
+S28W055
+S28W056
+S28W057
+S28W058
+S28W059
+S28W060
+S28W061
+S28W062
+S28W063
+S28W064
+S28W065
+S28W066
+S28W067
+S28W068
+S28W069
+S28W070
+S28W071
+S28W072
+S29W049
+S29W050
+S29W051
+S29W052
+S29W053
+S29W054
+S29W055
+S29W056
+S29W057
+S29W058
+S29W059
+S29W060
+S29W061
+S29W062
+S29W063
+S29W064
+S29W065
+S29W066
+S29W067
+S29W068
+S29W069
+S29W070
+S29W071
+S29W072
+S30W050
+S30W051
+S30W052
+S30W053
+S30W054
+S30W055
+S30W056
+S30W057
+S30W058
+S30W059
+S30W060
+S30W061
+S30W062
+S30W063
+S30W064
+S30W065
+S30W066
+S30W067
+S30W068
+S30W069
+S30W070
+S30W071
+S30W072
+S31W051
+S31W052
+S31W053
+S31W054
+S31W055
+S31W056
+S31W057
+S31W058
+S31W059
+S31W060
+S31W061
+S31W062
+S31W063
+S31W064
+S31W065
+S31W066
+S31W067
+S31W068
+S31W069
+S31W070
+S31W071
+S31W072
+S32W051
+S32W052
+S32W053
+S32W054
+S32W055
+S32W056
+S32W057
+S32W058
+S32W059
+S32W060
+S32W061
+S32W062
+S32W063
+S32W064
+S32W065
+S32W066
+S32W067
+S32W068
+S32W069
+S32W070
+S32W071
+S32W072
+S33W052
+S33W053
+S33W054
+S33W055
+S33W056
+S33W057
+S33W058
+S33W059
+S33W060
+S33W061
+S33W062
+S33W063
+S33W064
+S33W065
+S33W066
+S33W067
+S33W068
+S33W069
+S33W070
+S33W071
+S33W072
+S34W053
+S34W054
+S34W055
+S34W056
+S34W057
+S34W058
+S34W059
+S34W060
+S34W061
+S34W062
+S34W063
+S34W064
+S34W065
+S34W066
+S34W067
+S34W068
+S34W069
+S34W070
+S34W071
+S34W072
+S34W079
+S34W081
+S35W054
+S35W055
+S35W056
+S35W057
+S35W058
+S35W059
+S35W060
+S35W061
+S35W062
+S35W063
+S35W064
+S35W065
+S35W066
+S35W067
+S35W068
+S35W069
+S35W070
+S35W071
+S35W072
+S35W073
+S36W058
+S36W059
+S36W060
+S36W061
+S36W062
+S36W063
+S36W064
+S36W065
+S36W066
+S36W067
+S36W068
+S36W069
+S36W070
+S36W071
+S36W072
+S36W073
+S37W057
+S37W058
+S37W059
+S37W060
+S37W061
+S37W062
+S37W063
+S37W064
+S37W065
+S37W066
+S37W067
+S37W068
+S37W069
+S37W070
+S37W071
+S37W072
+S37W073
+S37W074
+S38W057
+S38W058
+S38W059
+S38W060
+S38W061
+S38W062
+S38W063
+S38W064
+S38W065
+S38W066
+S38W067
+S38W068
+S38W069
+S38W070
+S38W071
+S38W072
+S38W073
+S38W074
+S39W058
+S39W059
+S39W060
+S39W061
+S39W062
+S39W063
+S39W064
+S39W065
+S39W066
+S39W067
+S39W068
+S39W069
+S39W070
+S39W071
+S39W072
+S39W073
+S39W074
+S40W062
+S40W063
+S40W064
+S40W065
+S40W066
+S40W067
+S40W068
+S40W069
+S40W070
+S40W071
+S40W072
+S40W073
+S40W074
+S41W063
+S41W064
+S41W065
+S41W066
+S41W067
+S41W068
+S41W069
+S41W070
+S41W071
+S41W072
+S41W073
+S41W074
+S42W063
+S42W064
+S42W065
+S42W066
+S42W067
+S42W068
+S42W069
+S42W070
+S42W071
+S42W072
+S42W073
+S42W074
+S42W075
+S43W064
+S43W065
+S43W066
+S43W067
+S43W068
+S43W069
+S43W070
+S43W071
+S43W072
+S43W073
+S43W074
+S43W075
+S44W065
+S44W066
+S44W067
+S44W068
+S44W069
+S44W070
+S44W071
+S44W072
+S44W073
+S44W074
+S44W075
+S45W066
+S45W067
+S45W068
+S45W069
+S45W070
+S45W071
+S45W072
+S45W073
+S45W074
+S45W075
+S45W076
+S46W066
+S46W067
+S46W068
+S46W069
+S46W070
+S46W071
+S46W072
+S46W073
+S46W074
+S46W075
+S46W076
+S47W067
+S47W068
+S47W069
+S47W070
+S47W071
+S47W072
+S47W073
+S47W074
+S47W075
+S47W076
+S48W066
+S48W067
+S48W068
+S48W069
+S48W070
+S48W071
+S48W072
+S48W073
+S48W074
+S48W075
+S48W076
+S49W066
+S49W067
+S49W068
+S49W069
+S49W070
+S49W071
+S49W072
+S49W073
+S49W074
+S49W075
+S49W076
+S50W068
+S50W069
+S50W070
+S50W071
+S50W072
+S50W073
+S50W074
+S50W075
+S50W076
+S51W062
+S51W068
+S51W069
+S51W070
+S51W071
+S51W072
+S51W073
+S51W074
+S51W075
+S51W076
+S52W058
+S52W059
+S52W060
+S52W061
+S52W062
+S52W069
+S52W070
+S52W071
+S52W072
+S52W073
+S52W074
+S52W075
+S52W076
+S53W059
+S53W060
+S53W061
+S53W062
+S53W069
+S53W070
+S53W071
+S53W072
+S53W073
+S53W074
+S53W075
+S53W076
+S54W068
+S54W069
+S54W070
+S54W071
+S54W072
+S54W073
+S54W074
+S54W075
+S55W064
+S55W065
+S55W066
+S55W067
+S55W068
+S55W069
+S55W070
+S55W071
+S55W072
+S55W073
+S55W074
+S56W067
+S56W068
+S56W069
+S56W070
+S56W071
+S56W072
+s17w069
+
diff --git a/tim/prune/function/srtm/gen/tiles6.txt b/tim/prune/function/srtm/gen/tiles6.txt
new file mode 100644 (file)
index 0000000..959de45
--- /dev/null
@@ -0,0 +1,3251 @@
+Africa
+N00E006
+N00E009
+N00E010
+N00E011
+N00E012
+N00E013
+N00E014
+N00E015
+N00E016
+N00E017
+N00E018
+N00E019
+N00E020
+N00E021
+N00E022
+N00E023
+N00E024
+N00E025
+N00E026
+N00E027
+N00E028
+N00E029
+N00E030
+N00E031
+N00E032
+N00E033
+N00E034
+N00E035
+N00E036
+N00E037
+N00E038
+N00E039
+N00E040
+N00E041
+N00E042
+N00E043
+N01E007
+N01E009
+N01E010
+N01E011
+N01E012
+N01E013
+N01E014
+N01E015
+N01E016
+N01E017
+N01E018
+N01E019
+N01E020
+N01E021
+N01E022
+N01E023
+N01E024
+N01E025
+N01E026
+N01E027
+N01E028
+N01E029
+N01E030
+N01E031
+N01E032
+N01E033
+N01E034
+N01E035
+N01E036
+N01E037
+N01E038
+N01E039
+N01E040
+N01E041
+N01E042
+N01E043
+N01E044
+N01E045
+N02E009
+N02E010
+N02E011
+N02E012
+N02E013
+N02E014
+N02E015
+N02E016
+N02E017
+N02E018
+N02E019
+N02E020
+N02E021
+N02E022
+N02E023
+N02E024
+N02E025
+N02E026
+N02E027
+N02E028
+N02E029
+N02E030
+N02E031
+N02E032
+N02E033
+N02E034
+N02E035
+N02E036
+N02E037
+N02E038
+N02E039
+N02E040
+N02E041
+N02E042
+N02E043
+N02E044
+N02E045
+N02E046
+N03E008
+N03E009
+N03E010
+N03E011
+N03E012
+N03E013
+N03E014
+N03E015
+N03E016
+N03E017
+N03E018
+N03E019
+N03E020
+N03E021
+N03E022
+N03E023
+N03E024
+N03E025
+N03E026
+N03E027
+N03E028
+N03E029
+N03E030
+N03E031
+N03E032
+N03E033
+N03E034
+N03E035
+N03E036
+N03E037
+N03E038
+N03E039
+N03E040
+N03E041
+N03E042
+N03E043
+N03E044
+N03E045
+N03E046
+N03E047
+N04E005
+N04E006
+N04E007
+N04E008
+N04E009
+N04E010
+N04E011
+N04E012
+N04E013
+N04E014
+N04E015
+N04E016
+N04E017
+N04E018
+N04E019
+N04E020
+N04E021
+N04E022
+N04E023
+N04E024
+N04E025
+N04E026
+N04E027
+N04E028
+N04E029
+N04E030
+N04E031
+N04E032
+N04E033
+N04E034
+N04E035
+N04E036
+N04E037
+N04E038
+N04E039
+N04E040
+N04E041
+N04E042
+N04E043
+N04E044
+N04E045
+N04E046
+N04E047
+N04E048
+N04W002
+N04W003
+N04W006
+N04W007
+N04W008
+N04W009
+N04W010
+N05E000
+N05E001
+N05E004
+N05E005
+N05E006
+N05E007
+N05E008
+N05E009
+N05E010
+N05E011
+N05E012
+N05E013
+N05E014
+N05E015
+N05E016
+N05E017
+N05E018
+N05E019
+N05E020
+N05E021
+N05E022
+N05E023
+N05E024
+N05E025
+N05E026
+N05E027
+N05E028
+N05E029
+N05E030
+N05E031
+N05E032
+N05E033
+N05E034
+N05E035
+N05E036
+N05E037
+N05E038
+N05E039
+N05E040
+N05E041
+N05E042
+N05E043
+N05E044
+N05E045
+N05E046
+N05E047
+N05E048
+N05W001
+N05W002
+N05W003
+N05W004
+N05W005
+N05W006
+N05W007
+N05W008
+N05W009
+N05W010
+N05W011
+N06E000
+N06E001
+N06E002
+N06E003
+N06E004
+N06E005
+N06E006
+N06E007
+N06E008
+N06E009
+N06E010
+N06E011
+N06E012
+N06E013
+N06E014
+N06E015
+N06E016
+N06E017
+N06E018
+N06E019
+N06E020
+N06E021
+N06E022
+N06E023
+N06E024
+N06E025
+N06E026
+N06E027
+N06E028
+N06E029
+N06E030
+N06E031
+N06E032
+N06E033
+N06E034
+N06E035
+N06E036
+N06E037
+N06E038
+N06E039
+N06E040
+N06E041
+N06E042
+N06E043
+N06E044
+N06E045
+N06E046
+N06E047
+N06E048
+N06E049
+N06W001
+N06W002
+N06W003
+N06W004
+N06W005
+N06W006
+N06W007
+N06W008
+N06W009
+N06W010
+N06W011
+N06W012
+N07E000
+N07E001
+N07E002
+N07E003
+N07E004
+N07E005
+N07E006
+N07E007
+N07E008
+N07E009
+N07E010
+N07E011
+N07E012
+N07E013
+N07E014
+N07E015
+N07E016
+N07E017
+N07E018
+N07E019
+N07E020
+N07E021
+N07E022
+N07E023
+N07E024
+N07E025
+N07E026
+N07E027
+N07E028
+N07E029
+N07E030
+N07E031
+N07E032
+N07E033
+N07E034
+N07E035
+N07E036
+N07E037
+N07E038
+N07E039
+N07E040
+N07E041
+N07E042
+N07E043
+N07E044
+N07E045
+N07E046
+N07E047
+N07E048
+N07E049
+N07W001
+N07W002
+N07W003
+N07W004
+N07W005
+N07W006
+N07W007
+N07W008
+N07W009
+N07W010
+N07W011
+N07W012
+N07W013
+N07W014
+N08E000
+N08E001
+N08E002
+N08E003
+N08E004
+N08E005
+N08E006
+N08E007
+N08E008
+N08E009
+N08E010
+N08E011
+N08E012
+N08E013
+N08E014
+N08E015
+N08E016
+N08E017
+N08E018
+N08E019
+N08E020
+N08E021
+N08E022
+N08E023
+N08E024
+N08E025
+N08E026
+N08E027
+N08E028
+N08E029
+N08E030
+N08E031
+N08E032
+N08E033
+N08E034
+N08E035
+N08E036
+N08E037
+N08E038
+N08E039
+N08E040
+N08E041
+N08E042
+N08E043
+N08E044
+N08E045
+N08E046
+N08E047
+N08E048
+N08E049
+N08E050
+N08W001
+N08W002
+N08W003
+N08W004
+N08W005
+N08W006
+N08W007
+N08W008
+N08W009
+N08W010
+N08W011
+N08W012
+N08W013
+N08W014
+N09E000
+N09E001
+N09E002
+N09E003
+N09E004
+N09E005
+N09E006
+N09E007
+N09E008
+N09E009
+N09E010
+N09E011
+N09E012
+N09E013
+N09E014
+N09E015
+N09E016
+N09E017
+N09E018
+N09E019
+N09E020
+N09E021
+N09E022
+N09E023
+N09E024
+N09E025
+N09E026
+N09E027
+N09E028
+N09E029
+N09E030
+N09E031
+N09E032
+N09E033
+N09E034
+N09E035
+N09E036
+N09E037
+N09E038
+N09E039
+N09E040
+N09E041
+N09E042
+N09E043
+N09E044
+N09E045
+N09E046
+N09E047
+N09E048
+N09E049
+N09E050
+N09W001
+N09W002
+N09W003
+N09W004
+N09W005
+N09W006
+N09W007
+N09W008
+N09W009
+N09W010
+N09W011
+N09W012
+N09W013
+N09W014
+N09W015
+N10E000
+N10E001
+N10E002
+N10E003
+N10E004
+N10E005
+N10E006
+N10E007
+N10E008
+N10E009
+N10E010
+N10E011
+N10E012
+N10E013
+N10E014
+N10E015
+N10E016
+N10E017
+N10E018
+N10E019
+N10E020
+N10E021
+N10E022
+N10E023
+N10E024
+N10E025
+N10E026
+N10E027
+N10E028
+N10E029
+N10E030
+N10E031
+N10E032
+N10E033
+N10E034
+N10E035
+N10E036
+N10E037
+N10E038
+N10E039
+N10E040
+N10E041
+N10E042
+N10E043
+N10E044
+N10E045
+N10E046
+N10E047
+N10E048
+N10E049
+N10E050
+N10E051
+N10W001
+N10W002
+N10W003
+N10W004
+N10W005
+N10W006
+N10W007
+N10W008
+N10W009
+N10W010
+N10W011
+N10W012
+N10W013
+N10W014
+N10W015
+N10W016
+N11E000
+N11E001
+N11E002
+N11E003
+N11E004
+N11E005
+N11E006
+N11E007
+N11E008
+N11E009
+N11E010
+N11E011
+N11E012
+N11E013
+N11E014
+N11E015
+N11E016
+N11E017
+N11E018
+N11E019
+N11E020
+N11E021
+N11E022
+N11E023
+N11E024
+N11E025
+N11E026
+N11E027
+N11E028
+N11E029
+N11E030
+N11E031
+N11E032
+N11E033
+N11E034
+N11E035
+N11E036
+N11E037
+N11E038
+N11E039
+N11E040
+N11E041
+N11E042
+N11E043
+N11E047
+N11E048
+N11E049
+N11E050
+N11E051
+N11W001
+N11W002
+N11W003
+N11W004
+N11W005
+N11W006
+N11W007
+N11W008
+N11W009
+N11W010
+N11W011
+N11W012
+N11W013
+N11W014
+N11W015
+N11W016
+N11W017
+N12E000
+N12E001
+N12E002
+N12E003
+N12E004
+N12E005
+N12E006
+N12E007
+N12E008
+N12E009
+N12E010
+N12E011
+N12E012
+N12E013
+N12E014
+N12E015
+N12E016
+N12E017
+N12E018
+N12E019
+N12E020
+N12E021
+N12E022
+N12E023
+N12E024
+N12E025
+N12E026
+N12E027
+N12E028
+N12E029
+N12E030
+N12E031
+N12E032
+N12E033
+N12E034
+N12E035
+N12E036
+N12E037
+N12E038
+N12E039
+N12E040
+N12E041
+N12E042
+N12E043
+N12E044
+N12E045
+N12E052
+N12E053
+N12E054
+N12W001
+N12W002
+N12W003
+N12W004
+N12W005
+N12W006
+N12W007
+N12W008
+N12W009
+N12W010
+N12W011
+N12W012
+N12W013
+N12W014
+N12W015
+N12W016
+N12W017
+N13E000
+N13E001
+N13E002
+N13E003
+N13E004
+N13E005
+N13E006
+N13E007
+N13E008
+N13E009
+N13E010
+N13E011
+N13E012
+N13E013
+N13E014
+N13E015
+N13E016
+N13E017
+N13E018
+N13E019
+N13E020
+N13E021
+N13E022
+N13E023
+N13E024
+N13E025
+N13E026
+N13E027
+N13E028
+N13E029
+N13E030
+N13E031
+N13E032
+N13E033
+N13E034
+N13E035
+N13E036
+N13E037
+N13E038
+N13E039
+N13E040
+N13E041
+N13E042
+N13E043
+N13E044
+N13E045
+N13E046
+N13E047
+N13E048
+N13W001
+N13W002
+N13W003
+N13W004
+N13W005
+N13W006
+N13W007
+N13W008
+N13W009
+N13W010
+N13W011
+N13W012
+N13W013
+N13W014
+N13W015
+N13W016
+N13W017
+N14E000
+N14E001
+N14E002
+N14E003
+N14E004
+N14E005
+N14E006
+N14E007
+N14E008
+N14E009
+N14E010
+N14E011
+N14E012
+N14E013
+N14E014
+N14E015
+N14E016
+N14E017
+N14E018
+N14E019
+N14E020
+N14E021
+N14E022
+N14E023
+N14E024
+N14E025
+N14E026
+N14E027
+N14E028
+N14E029
+N14E030
+N14E031
+N14E032
+N14E033
+N14E034
+N14E035
+N14E036
+N14E037
+N14E038
+N14E039
+N14E040
+N14E041
+N14E042
+N14E043
+N14E044
+N14E045
+N14E046
+N14E047
+N14E048
+N14E049
+N14E050
+N14W001
+N14W002
+N14W003
+N14W004
+N14W005
+N14W006
+N14W007
+N14W008
+N14W009
+N14W010
+N14W011
+N14W012
+N14W013
+N14W014
+N14W015
+N14W016
+N14W017
+N14W018
+N14W024
+N14W025
+N15E000
+N15E001
+N15E002
+N15E003
+N15E004
+N15E005
+N15E006
+N15E007
+N15E008
+N15E009
+N15E010
+N15E011
+N15E012
+N15E013
+N15E014
+N15E015
+N15E016
+N15E017
+N15E018
+N15E019
+N15E020
+N15E021
+N15E022
+N15E023
+N15E024
+N15E025
+N15E026
+N15E027
+N15E028
+N15E029
+N15E030
+N15E031
+N15E032
+N15E033
+N15E034
+N15E035
+N15E036
+N15E037
+N15E038
+N15E039
+N15E040
+N15E041
+N15E042
+N15E043
+N15E044
+N15E045
+N15E046
+N15E047
+N15E048
+N15E049
+N15E050
+N15E051
+N15E052
+N15W001
+N15W002
+N15W003
+N15W004
+N15W005
+N15W006
+N15W007
+N15W008
+N15W009
+N15W010
+N15W011
+N15W012
+N15W013
+N15W014
+N15W015
+N15W016
+N15W017
+N15W018
+N15W023
+N15W024
+N15W025
+N16E000
+N16E001
+N16E002
+N16E003
+N16E004
+N16E005
+N16E006
+N16E007
+N16E008
+N16E009
+N16E010
+N16E011
+N16E012
+N16E013
+N16E014
+N16E015
+N16E016
+N16E017
+N16E018
+N16E019
+N16E020
+N16E021
+N16E022
+N16E023
+N16E024
+N16E025
+N16E026
+N16E027
+N16E028
+N16E029
+N16E030
+N16E031
+N16E032
+N16E033
+N16E034
+N16E035
+N16E036
+N16E037
+N16E038
+N16E039
+N16E040
+N16E041
+N16E042
+N16E043
+N16E044
+N16E045
+N16E046
+N16E047
+N16E048
+N16E049
+N16E050
+N16E051
+N16E052
+N16E053
+N16E054
+N16E055
+N16W001
+N16W002
+N16W003
+N16W004
+N16W005
+N16W006
+N16W007
+N16W008
+N16W009
+N16W010
+N16W011
+N16W012
+N16W013
+N16W014
+N16W015
+N16W016
+N16W017
+N16W023
+N16W025
+N16W026
+N17E000
+N17E001
+N17E002
+N17E003
+N17E004
+N17E005
+N17E006
+N17E007
+N17E008
+N17E009
+N17E010
+N17E011
+N17E012
+N17E013
+N17E014
+N17E015
+N17E016
+N17E017
+N17E018
+N17E019
+N17E020
+N17E021
+N17E022
+N17E023
+N17E024
+N17E025
+N17E026
+N17E027
+N17E028
+N17E029
+N17E030
+N17E031
+N17E032
+N17E033
+N17E034
+N17E035
+N17E036
+N17E037
+N17E038
+N17E039
+N17E041
+N17E042
+N17E043
+N17E044
+N17E045
+N17E046
+N17E047
+N17E048
+N17E049
+N17E050
+N17E051
+N17E052
+N17E053
+N17E054
+N17E055
+N17E056
+N17W001
+N17W002
+N17W003
+N17W004
+N17W005
+N17W006
+N17W007
+N17W008
+N17W009
+N17W010
+N17W011
+N17W012
+N17W013
+N17W014
+N17W015
+N17W016
+N17W017
+N17W025
+N17W026
+N18E000
+N18E001
+N18E002
+N18E003
+N18E004
+N18E005
+N18E006
+N18E007
+N18E008
+N18E009
+N18E010
+N18E011
+N18E012
+N18E013
+N18E014
+N18E015
+N18E016
+N18E017
+N18E018
+N18E019
+N18E020
+N18E021
+N18E022
+N18E023
+N18E024
+N18E025
+N18E026
+N18E027
+N18E028
+N18E029
+N18E030
+N18E031
+N18E032
+N18E033
+N18E034
+N18E035
+N18E036
+N18E037
+N18E038
+N18E040
+N18E041
+N18E042
+N18E043
+N18E044
+N18E045
+N18E046
+N18E047
+N18E048
+N18E049
+N18E050
+N18E051
+N18E052
+N18E053
+N18E054
+N18E055
+N18E056
+N18E057
+N18W001
+N18W002
+N18W003
+N18W004
+N18W005
+N18W006
+N18W007
+N18W008
+N18W009
+N18W010
+N18W011
+N18W012
+N18W013
+N18W014
+N18W015
+N18W016
+N18W017
+N19E000
+N19E001
+N19E002
+N19E003
+N19E004
+N19E005
+N19E006
+N19E007
+N19E008
+N19E009
+N19E010
+N19E011
+N19E012
+N19E013
+N19E014
+N19E015
+N19E016
+N19E017
+N19E018
+N19E019
+N19E020
+N19E021
+N19E022
+N19E023
+N19E024
+N19E025
+N19E026
+N19E027
+N19E028
+N19E029
+N19E030
+N19E031
+N19E032
+N19E033
+N19E034
+N19E035
+N19E036
+N19E037
+N19E038
+N19E039
+N19E040
+N19E041
+N19E042
+N19E043
+N19E044
+N19E045
+N19E046
+N19E047
+N19E048
+N19E049
+N19E050
+N19E051
+N19E052
+N19E053
+N19E054
+N19E055
+N19E056
+N19E057
+N19W001
+N19W002
+N19W003
+N19W004
+N19W005
+N19W006
+N19W007
+N19W008
+N19W009
+N19W010
+N19W011
+N19W012
+N19W013
+N19W014
+N19W015
+N19W016
+N19W017
+N20E000
+N20E001
+N20E002
+N20E003
+N20E004
+N20E005
+N20E006
+N20E007
+N20E008
+N20E009
+N20E010
+N20E011
+N20E012
+N20E013
+N20E014
+N20E015
+N20E016
+N20E017
+N20E018
+N20E019
+N20E020
+N20E021
+N20E022
+N20E023
+N20E024
+N20E025
+N20E026
+N20E027
+N20E028
+N20E029
+N20E030
+N20E031
+N20E032
+N20E033
+N20E034
+N20E035
+N20E036
+N20E037
+N20E039
+N20E040
+N20E041
+N20E042
+N20E043
+N20E044
+N20E045
+N20E046
+N20E047
+N20E048
+N20E049
+N20E050
+N20E051
+N20E052
+N20E053
+N20E054
+N20E055
+N20E056
+N20E057
+N20E058
+N20W001
+N20W002
+N20W003
+N20W004
+N20W005
+N20W006
+N20W007
+N20W008
+N20W009
+N20W010
+N20W011
+N20W012
+N20W013
+N20W014
+N20W015
+N20W016
+N20W017
+N20W018
+N21E000
+N21E001
+N21E002
+N21E003
+N21E004
+N21E005
+N21E006
+N21E007
+N21E008
+N21E009
+N21E010
+N21E011
+N21E012
+N21E013
+N21E014
+N21E015
+N21E016
+N21E017
+N21E018
+N21E019
+N21E020
+N21E021
+N21E022
+N21E023
+N21E024
+N21E025
+N21E026
+N21E027
+N21E028
+N21E029
+N21E030
+N21E031
+N21E032
+N21E033
+N21E034
+N21E035
+N21E036
+N21E037
+N21E038
+N21E039
+N21E040
+N21E041
+N21E042
+N21E043
+N21E044
+N21E045
+N21E046
+N21E047
+N21E048
+N21E049
+N21E050
+N21E051
+N21E052
+N21E053
+N21E054
+N21E055
+N21E056
+N21E057
+N21E058
+N21E059
+N21W001
+N21W002
+N21W003
+N21W004
+N21W005
+N21W006
+N21W007
+N21W008
+N21W009
+N21W010
+N21W011
+N21W012
+N21W013
+N21W014
+N21W015
+N21W016
+N21W017
+N21W018
+N22E000
+N22E001
+N22E002
+N22E003
+N22E004
+N22E005
+N22E006
+N22E007
+N22E008
+N22E009
+N22E010
+N22E011
+N22E012
+N22E013
+N22E014
+N22E015
+N22E016
+N22E017
+N22E018
+N22E019
+N22E020
+N22E021
+N22E022
+N22E023
+N22E024
+N22E025
+N22E026
+N22E027
+N22E028
+N22E029
+N22E030
+N22E031
+N22E032
+N22E033
+N22E034
+N22E035
+N22E036
+N22E038
+N22E039
+N22E040
+N22E041
+N22E042
+N22E043
+N22E044
+N22E045
+N22E046
+N22E047
+N22E048
+N22E049
+N22E050
+N22E051
+N22E052
+N22E053
+N22E054
+N22E055
+N22E056
+N22E057
+N22E058
+N22E059
+N22W001
+N22W002
+N22W003
+N22W004
+N22W005
+N22W006
+N22W007
+N22W008
+N22W009
+N22W010
+N22W011
+N22W012
+N22W013
+N22W014
+N22W015
+N22W016
+N22W017
+N23E000
+N23E001
+N23E002
+N23E003
+N23E004
+N23E005
+N23E006
+N23E007
+N23E008
+N23E009
+N23E010
+N23E011
+N23E012
+N23E013
+N23E014
+N23E015
+N23E016
+N23E017
+N23E018
+N23E019
+N23E020
+N23E021
+N23E022
+N23E023
+N23E024
+N23E025
+N23E026
+N23E027
+N23E028
+N23E029
+N23E030
+N23E031
+N23E032
+N23E033
+N23E034
+N23E035
+N23E036
+N23E038
+N23E039
+N23E040
+N23E041
+N23E042
+N23E043
+N23E044
+N23E045
+N23E046
+N23E047
+N23E048
+N23E049
+N23E050
+N23E051
+N23E052
+N23E053
+N23E054
+N23E055
+N23E056
+N23E057
+N23E058
+N23E059
+N23W001
+N23W002
+N23W003
+N23W004
+N23W005
+N23W006
+N23W007
+N23W008
+N23W009
+N23W010
+N23W011
+N23W012
+N23W013
+N23W014
+N23W015
+N23W016
+N23W017
+N24E000
+N24E001
+N24E002
+N24E003
+N24E004
+N24E005
+N24E006
+N24E007
+N24E008
+N24E009
+N24E010
+N24E011
+N24E013
+N24E014
+N24E015
+N24E016
+N24E017
+N24E018
+N24E019
+N24E020
+N24E021
+N24E022
+N24E023
+N24E024
+N24E025
+N24E026
+N24E027
+N24E028
+N24E029
+N24E030
+N24E031
+N24E032
+N24E033
+N24E034
+N24E035
+N24E037
+N24E038
+N24E039
+N24E040
+N24E041
+N24E042
+N24E043
+N24E044
+N24E045
+N24E046
+N24E047
+N24E048
+N24E049
+N24E050
+N24E051
+N24E052
+N24E053
+N24E054
+N24E055
+N24E056
+N24E057
+N24W001
+N24W002
+N24W003
+N24W004
+N24W005
+N24W006
+N24W007
+N24W008
+N24W009
+N24W010
+N24W011
+N24W012
+N24W013
+N24W014
+N24W015
+N24W016
+N25E000
+N25E001
+N25E002
+N25E003
+N25E004
+N25E005
+N25E006
+N25E007
+N25E008
+N25E009
+N25E010
+N25E011
+N25E012
+N25E013
+N25E014
+N25E015
+N25E016
+N25E017
+N25E018
+N25E019
+N25E020
+N25E021
+N25E022
+N25E023
+N25E024
+N25E025
+N25E026
+N25E027
+N25E028
+N25E029
+N25E030
+N25E031
+N25E032
+N25E033
+N25E034
+N25E036
+N25E037
+N25E038
+N25E039
+N25E040
+N25E041
+N25E042
+N25E043
+N25E044
+N25E045
+N25E046
+N25E047
+N25E048
+N25E049
+N25E050
+N25E051
+N25E052
+N25E054
+N25E055
+N25E056
+N25E057
+N25E058
+N25E059
+N25W001
+N25W002
+N25W003
+N25W004
+N25W005
+N25W006
+N25W007
+N25W008
+N25W009
+N25W010
+N25W011
+N25W012
+N25W013
+N25W014
+N25W015
+N26E000
+N26E001
+N26E002
+N26E003
+N26E004
+N26E005
+N26E006
+N26E007
+N26E008
+N26E009
+N26E010
+N26E011
+N26E012
+N26E013
+N26E014
+N26E015
+N26E016
+N26E017
+N26E018
+N26E019
+N26E020
+N26E021
+N26E022
+N26E023
+N26E024
+N26E025
+N26E026
+N26E027
+N26E028
+N26E029
+N26E030
+N26E031
+N26E032
+N26E033
+N26E034
+N26E035
+N26E036
+N26E037
+N26E038
+N26E039
+N26E040
+N26E041
+N26E042
+N26E043
+N26E044
+N26E045
+N26E046
+N26E047
+N26E048
+N26E049
+N26E050
+N26E051
+N26E053
+N26E054
+N26E055
+N26E056
+N26E057
+N26E058
+N26E059
+N26W001
+N26W002
+N26W003
+N26W004
+N26W005
+N26W006
+N26W007
+N26W008
+N26W009
+N26W010
+N26W011
+N26W012
+N26W013
+N26W014
+N26W015
+N27E000
+N27E001
+N27E002
+N27E003
+N27E004
+N27E005
+N27E006
+N27E007
+N27E008
+N27E009
+N27E010
+N27E011
+N27E012
+N27E013
+N27E014
+N27E015
+N27E016
+N27E017
+N27E018
+N27E019
+N27E020
+N27E021
+N27E022
+N27E023
+N27E024
+N27E025
+N27E026
+N27E027
+N27E028
+N27E029
+N27E030
+N27E031
+N27E032
+N27E033
+N27E034
+N27E035
+N27E036
+N27E037
+N27E038
+N27E039
+N27E040
+N27E041
+N27E042
+N27E043
+N27E044
+N27E045
+N27E046
+N27E047
+N27E048
+N27E049
+N27E050
+N27E051
+N27E052
+N27E053
+N27E054
+N27E055
+N27E056
+N27E057
+N27E058
+N27E059
+N27W001
+N27W002
+N27W003
+N27W004
+N27W005
+N27W006
+N27W007
+N27W008
+N27W009
+N27W010
+N27W011
+N27W012
+N27W013
+N27W014
+N27W016
+N27W017
+N27W018
+N27W019
+N28E000
+N28E001
+N28E002
+N28E003
+N28E004
+N28E005
+N28E006
+N28E007
+N28E008
+N28E009
+N28E010
+N28E011
+N28E012
+N28E013
+N28E014
+N28E015
+N28E016
+N28E017
+N28E018
+N28E019
+N28E020
+N28E021
+N28E022
+N28E023
+N28E024
+N28E025
+N28E026
+N28E027
+N28E028
+N28E029
+N28E030
+N28E031
+N28E032
+N28E033
+N28E034
+N28E035
+N28E036
+N28E037
+N28E038
+N28E039
+N28E040
+N28E041
+N28E042
+N28E043
+N28E044
+N28E045
+N28E046
+N28E047
+N28E048
+N28E050
+N28E051
+N28E052
+N28E053
+N28E054
+N28E055
+N28E056
+N28E057
+N28E058
+N28E059
+N28W001
+N28W002
+N28W003
+N28W004
+N28W005
+N28W006
+N28W007
+N28W008
+N28W009
+N28W010
+N28W011
+N28W012
+N28W013
+N28W014
+N28W015
+N28W016
+N28W017
+N28W018
+N28W019
+N29E000
+N29E001
+N29E002
+N29E003
+N29E004
+N29E005
+N29E006
+N29E007
+N29E008
+N29E009
+N29E010
+N29E011
+N29E012
+N29E013
+N29E014
+N29E015
+N29E016
+N29E017
+N29E018
+N29E019
+N29E020
+N29E021
+N29E022
+N29E023
+N29E024
+N29E025
+N29E026
+N29E027
+N29E028
+N29E029
+N29E030
+N29E031
+N29E032
+N29E033
+N29E034
+N29E035
+N29E036
+N29E037
+N29E038
+N29E039
+N29E040
+N29E041
+N29E042
+N29E043
+N29E044
+N29E045
+N29E046
+N29E047
+N29E048
+N29E049
+N29E050
+N29E051
+N29E052
+N29E053
+N29E054
+N29E055
+N29E056
+N29E057
+N29E058
+N29E059
+N29W001
+N29W002
+N29W003
+N29W004
+N29W005
+N29W006
+N29W007
+N29W008
+N29W009
+N29W010
+N29W011
+N29W014
+N30E000
+N30E001
+N30E002
+N30E003
+N30E004
+N30E005
+N30E006
+N30E007
+N30E008
+N30E009
+N30E010
+N30E011
+N30E012
+N30E013
+N30E014
+N30E015
+N30E016
+N30E017
+N30E018
+N30E019
+N30E020
+N30E021
+N30E022
+N30E023
+N30E024
+N30E025
+N30E026
+N30E027
+N30E028
+N30E029
+N30E030
+N30E031
+N30E032
+N30E033
+N30E034
+N30E035
+N30E036
+N30E037
+N30E038
+N30E039
+N30E040
+N30E041
+N30E042
+N30E043
+N30E044
+N30E045
+N30E046
+N30E047
+N30E048
+N30E049
+N30E050
+N30E051
+N30E052
+N30E053
+N30E054
+N30E055
+N30E056
+N30E057
+N30E058
+N30E059
+N30W001
+N30W002
+N30W003
+N30W004
+N30W005
+N30W006
+N30W007
+N30W008
+N30W009
+N30W010
+N30W016
+N30W017
+N31E000
+N31E001
+N31E002
+N31E003
+N31E004
+N31E005
+N31E006
+N31E007
+N31E008
+N31E009
+N31E010
+N31E011
+N31E012
+N31E013
+N31E014
+N31E015
+N31E016
+N31E017
+N31E019
+N31E020
+N31E021
+N31E022
+N31E023
+N31E024
+N31E025
+N31E026
+N31E027
+N31E028
+N31E029
+N31E030
+N31E031
+N31E032
+N31E033
+N31E034
+N31E035
+N31E036
+N31E037
+N31E038
+N31E039
+N31E040
+N31E041
+N31E042
+N31E043
+N31E044
+N31E045
+N31E046
+N31E047
+N31E048
+N31E049
+N31E050
+N31E051
+N31E052
+N31E053
+N31E054
+N31E055
+N31E056
+N31E057
+N31E058
+N31E059
+N31W001
+N31W002
+N31W003
+N31W004
+N31W005
+N31W006
+N31W007
+N31W008
+N31W009
+N31W010
+N32E000
+N32E001
+N32E002
+N32E003
+N32E004
+N32E005
+N32E006
+N32E007
+N32E008
+N32E009
+N32E010
+N32E011
+N32E012
+N32E013
+N32E014
+N32E015
+N32E019
+N32E020
+N32E021
+N32E022
+N32E023
+N32E024
+N32E034
+N32E035
+N32E036
+N32E037
+N32E038
+N32E039
+N32E040
+N32E041
+N32E042
+N32E043
+N32E044
+N32E045
+N32E046
+N32E047
+N32E048
+N32E049
+N32E050
+N32E051
+N32E052
+N32E053
+N32E054
+N32E055
+N32E056
+N32E057
+N32E058
+N32E059
+N32W001
+N32W002
+N32W003
+N32W004
+N32W005
+N32W006
+N32W007
+N32W008
+N32W009
+N32W010
+N32W017
+N32W018
+N33E000
+N33E001
+N33E002
+N33E003
+N33E004
+N33E005
+N33E006
+N33E007
+N33E008
+N33E009
+N33E010
+N33E011
+N33E035
+N33E036
+N33E037
+N33E038
+N33E039
+N33E040
+N33E041
+N33E042
+N33E043
+N33E044
+N33E045
+N33E046
+N33E047
+N33E048
+N33E049
+N33E050
+N33E051
+N33E052
+N33E053
+N33E054
+N33E055
+N33E056
+N33E057
+N33E058
+N33E059
+N33W001
+N33W002
+N33W003
+N33W004
+N33W005
+N33W006
+N33W007
+N33W008
+N33W009
+N33W017
+N34E000
+N34E001
+N34E002
+N34E003
+N34E004
+N34E005
+N34E006
+N34E007
+N34E008
+N34E009
+N34E010
+N34E011
+N34E023
+N34E024
+N34E025
+N34E026
+N34E032
+N34E033
+N34E034
+N34E035
+N34E036
+N34E037
+N34E038
+N34E039
+N34E040
+N34E041
+N34E042
+N34E043
+N34E044
+N34E045
+N34E046
+N34E047
+N34E048
+N34E049
+N34E050
+N34E051
+N34E052
+N34E053
+N34E054
+N34E055
+N34E056
+N34E057
+N34E058
+N34E059
+N34W001
+N34W002
+N34W003
+N34W004
+N34W005
+N34W006
+N34W007
+N36W026
+N37W025
+N37W026
+N38W028
+N38W029
+N39W028
+N39W029
+N39W032
+S01E006
+S01E008
+S01E009
+S01E010
+S01E011
+S01E012
+S01E013
+S01E014
+S01E015
+S01E016
+S01E017
+S01E018
+S01E019
+S01E020
+S01E021
+S01E022
+S01E023
+S01E024
+S01E025
+S01E026
+S01E027
+S01E028
+S01E029
+S01E030
+S01E031
+S01E032
+S01E033
+S01E034
+S01E035
+S01E036
+S01E037
+S01E038
+S01E039
+S01E040
+S01E041
+S01E042
+S02E005
+S02E008
+S02E009
+S02E010
+S02E011
+S02E012
+S02E013
+S02E014
+S02E015
+S02E016
+S02E017
+S02E018
+S02E019
+S02E020
+S02E021
+S02E022
+S02E023
+S02E024
+S02E025
+S02E026
+S02E027
+S02E028
+S02E029
+S02E030
+S02E031
+S02E032
+S02E033
+S02E034
+S02E035
+S02E036
+S02E037
+S02E038
+S02E039
+S02E040
+S02E041
+S02E042
+S03E009
+S03E010
+S03E011
+S03E012
+S03E013
+S03E014
+S03E015
+S03E016
+S03E017
+S03E018
+S03E019
+S03E020
+S03E021
+S03E022
+S03E023
+S03E024
+S03E025
+S03E026
+S03E027
+S03E028
+S03E029
+S03E030
+S03E031
+S03E032
+S03E033
+S03E034
+S03E035
+S03E036
+S03E037
+S03E038
+S03E039
+S03E040
+S03E041
+S04E010
+S04E011
+S04E012
+S04E013
+S04E014
+S04E015
+S04E016
+S04E017
+S04E018
+S04E019
+S04E020
+S04E021
+S04E022
+S04E023
+S04E024
+S04E025
+S04E026
+S04E027
+S04E028
+S04E029
+S04E030
+S04E031
+S04E032
+S04E033
+S04E034
+S04E035
+S04E036
+S04E037
+S04E038
+S04E039
+S04E040
+S04E055
+S05E011
+S05E012
+S05E013
+S05E014
+S05E015
+S05E016
+S05E017
+S05E018
+S05E019
+S05E020
+S05E021
+S05E022
+S05E023
+S05E024
+S05E025
+S05E026
+S05E027
+S05E028
+S05E029
+S05E030
+S05E031
+S05E032
+S05E033
+S05E034
+S05E035
+S05E036
+S05E037
+S05E038
+S05E039
+S05E053
+S05E055
+S06E011
+S06E012
+S06E013
+S06E014
+S06E015
+S06E016
+S06E017
+S06E018
+S06E019
+S06E020
+S06E021
+S06E022
+S06E023
+S06E024
+S06E025
+S06E026
+S06E027
+S06E028
+S06E029
+S06E030
+S06E031
+S06E032
+S06E033
+S06E034
+S06E035
+S06E036
+S06E037
+S06E038
+S06E039
+S06E053
+S06E055
+S07E012
+S07E013
+S07E014
+S07E015
+S07E016
+S07E017
+S07E018
+S07E019
+S07E020
+S07E021
+S07E022
+S07E023
+S07E024
+S07E025
+S07E026
+S07E027
+S07E028
+S07E029
+S07E030
+S07E031
+S07E032
+S07E033
+S07E034
+S07E035
+S07E036
+S07E037
+S07E038
+S07E039
+S07E052
+S07E053
+S08E012
+S08E013
+S08E014
+S08E015
+S08E016
+S08E017
+S08E018
+S08E019
+S08E020
+S08E021
+S08E022
+S08E023
+S08E024
+S08E025
+S08E026
+S08E027
+S08E028
+S08E029
+S08E030
+S08E031
+S08E032
+S08E033
+S08E034
+S08E035
+S08E036
+S08E037
+S08E038
+S08E039
+S08E052
+S08E056
+S09E013
+S09E014
+S09E015
+S09E016
+S09E017
+S09E018
+S09E019
+S09E020
+S09E021
+S09E022
+S09E023
+S09E024
+S09E025
+S09E026
+S09E027
+S09E028
+S09E029
+S09E030
+S09E031
+S09E032
+S09E033
+S09E034
+S09E035
+S09E036
+S09E037
+S09E038
+S09E039
+S10E012
+S10E013
+S10E014
+S10E015
+S10E016
+S10E017
+S10E018
+S10E019
+S10E020
+S10E021
+S10E022
+S10E023
+S10E024
+S10E025
+S10E026
+S10E027
+S10E028
+S10E029
+S10E030
+S10E031
+S10E032
+S10E033
+S10E034
+S10E035
+S10E036
+S10E037
+S10E038
+S10E039
+S10E046
+S10E047
+S10E050
+S10E051
+S11E013
+S11E014
+S11E015
+S11E016
+S11E017
+S11E018
+S11E019
+S11E020
+S11E021
+S11E022
+S11E023
+S11E024
+S11E025
+S11E026
+S11E027
+S11E028
+S11E029
+S11E030
+S11E031
+S11E032
+S11E033
+S11E034
+S11E035
+S11E036
+S11E037
+S11E038
+S11E039
+S11E040
+S11E047
+S11E051
+S11E056
+S12E013
+S12E014
+S12E015
+S12E016
+S12E017
+S12E018
+S12E019
+S12E020
+S12E021
+S12E022
+S12E023
+S12E024
+S12E025
+S12E026
+S12E027
+S12E028
+S12E029
+S12E030
+S12E031
+S12E032
+S12E033
+S12E034
+S12E035
+S12E036
+S12E037
+S12E038
+S12E039
+S12E040
+S12E043
+S12E047
+S12E049
+S13E012
+S13E013
+S13E014
+S13E015
+S13E016
+S13E017
+S13E018
+S13E019
+S13E020
+S13E021
+S13E022
+S13E023
+S13E024
+S13E025
+S13E026
+S13E027
+S13E028
+S13E029
+S13E030
+S13E031
+S13E032
+S13E033
+S13E034
+S13E035
+S13E036
+S13E037
+S13E038
+S13E039
+S13E040
+S13E043
+S13E044
+S13E045
+S13E048
+S13E049
+S14E012
+S14E013
+S14E014
+S14E015
+S14E016
+S14E017
+S14E018
+S14E019
+S14E020
+S14E021
+S14E022
+S14E023
+S14E024
+S14E025
+S14E026
+S14E027
+S14E028
+S14E029
+S14E030
+S14E031
+S14E032
+S14E033
+S14E034
+S14E035
+S14E036
+S14E037
+S14E038
+S14E039
+S14E040
+S14E045
+S14E047
+S14E048
+S14E049
+S14E050
+S15E012
+S15E013
+S15E014
+S15E015
+S15E016
+S15E017
+S15E018
+S15E019
+S15E020
+S15E021
+S15E022
+S15E023
+S15E024
+S15E025
+S15E026
+S15E027
+S15E028
+S15E029
+S15E030
+S15E031
+S15E032
+S15E033
+S15E034
+S15E035
+S15E036
+S15E037
+S15E038
+S15E039
+S15E040
+S15E047
+S15E048
+S15E049
+S15E050
+S16E011
+S16E012
+S16E013
+S16E014
+S16E015
+S16E016
+S16E017
+S16E018
+S16E019
+S16E020
+S16E021
+S16E022
+S16E023
+S16E024
+S16E025
+S16E026
+S16E027
+S16E028
+S16E029
+S16E030
+S16E031
+S16E032
+S16E033
+S16E034
+S16E035
+S16E036
+S16E037
+S16E038
+S16E039
+S16E040
+S16E045
+S16E046
+S16E047
+S16E048
+S16E049
+S16E050
+S16E054
+S17E011
+S17E012
+S17E013
+S17E014
+S17E015
+S17E016
+S17E017
+S17E018
+S17E019
+S17E020
+S17E021
+S17E022
+S17E023
+S17E024
+S17E025
+S17E026
+S17E027
+S17E028
+S17E029
+S17E030
+S17E031
+S17E032
+S17E033
+S17E034
+S17E035
+S17E036
+S17E037
+S17E038
+S17E039
+S17E040
+S17E043
+S17E044
+S17E045
+S17E046
+S17E047
+S17E048
+S17E049
+S17E050
+S17E059
+S18E011
+S18E012
+S18E013
+S18E014
+S18E015
+S18E016
+S18E017
+S18E018
+S18E019
+S18E020
+S18E021
+S18E022
+S18E023
+S18E024
+S18E025
+S18E026
+S18E027
+S18E028
+S18E029
+S18E030
+S18E031
+S18E032
+S18E033
+S18E034
+S18E035
+S18E036
+S18E037
+S18E038
+S18E039
+S18E042
+S18E043
+S18E044
+S18E045
+S18E046
+S18E047
+S18E048
+S18E049
+S19E011
+S19E012
+S19E013
+S19E014
+S19E015
+S19E016
+S19E017
+S19E018
+S19E019
+S19E020
+S19E021
+S19E022
+S19E023
+S19E024
+S19E025
+S19E026
+S19E027
+S19E028
+S19E029
+S19E030
+S19E031
+S19E032
+S19E033
+S19E034
+S19E035
+S19E036
+S19E037
+S19E043
+S19E044
+S19E045
+S19E046
+S19E047
+S19E048
+S19E049
+S20E012
+S20E013
+S20E014
+S20E015
+S20E016
+S20E017
+S20E018
+S20E019
+S20E020
+S20E021
+S20E022
+S20E023
+S20E024
+S20E025
+S20E026
+S20E027
+S20E028
+S20E029
+S20E030
+S20E031
+S20E032
+S20E033
+S20E034
+S20E035
+S20E044
+S20E045
+S20E046
+S20E047
+S20E048
+S20E049
+S20E057
+S20E063
+S21E013
+S21E014
+S21E015
+S21E016
+S21E017
+S21E018
+S21E019
+S21E020
+S21E021
+S21E022
+S21E023
+S21E024
+S21E025
+S21E026
+S21E027
+S21E028
+S21E029
+S21E030
+S21E031
+S21E032
+S21E033
+S21E034
+S21E035
+S21E043
+S21E044
+S21E045
+S21E046
+S21E047
+S21E048
+S21E055
+S21E057
+S22E013
+S22E014
+S22E015
+S22E016
+S22E017
+S22E018
+S22E019
+S22E020
+S22E021
+S22E022
+S22E023
+S22E024
+S22E025
+S22E026
+S22E027
+S22E028
+S22E029
+S22E030
+S22E031
+S22E032
+S22E033
+S22E034
+S22E035
+S22E043
+S22E044
+S22E045
+S22E046
+S22E047
+S22E048
+S22E055
+S23E014
+S23E015
+S23E016
+S23E017
+S23E018
+S23E019
+S23E020
+S23E021
+S23E022
+S23E023
+S23E024
+S23E025
+S23E026
+S23E027
+S23E028
+S23E029
+S23E030
+S23E031
+S23E032
+S23E033
+S23E034
+S23E035
+S23E040
+S23E043
+S23E044
+S23E045
+S23E046
+S23E047
+S23E048
+S24E014
+S24E015
+S24E016
+S24E017
+S24E018
+S24E019
+S24E020
+S24E021
+S24E022
+S24E023
+S24E024
+S24E025
+S24E026
+S24E027
+S24E028
+S24E029
+S24E030
+S24E031
+S24E032
+S24E033
+S24E034
+S24E035
+S24E043
+S24E044
+S24E045
+S24E046
+S24E047
+S25E014
+S25E015
+S25E016
+S25E017
+S25E018
+S25E019
+S25E020
+S25E021
+S25E022
+S25E023
+S25E024
+S25E025
+S25E026
+S25E027
+S25E028
+S25E029
+S25E030
+S25E031
+S25E032
+S25E033
+S25E034
+S25E035
+S25E043
+S25E044
+S25E045
+S25E046
+S25E047
+S26E014
+S26E015
+S26E016
+S26E017
+S26E018
+S26E019
+S26E020
+S26E021
+S26E022
+S26E023
+S26E024
+S26E025
+S26E026
+S26E027
+S26E028
+S26E029
+S26E030
+S26E031
+S26E032
+S26E033
+S26E034
+S26E044
+S26E045
+S26E046
+S26E047
+S27E014
+S27E015
+S27E016
+S27E017
+S27E018
+S27E019
+S27E020
+S27E021
+S27E022
+S27E023
+S27E024
+S27E025
+S27E026
+S27E027
+S27E028
+S27E029
+S27E030
+S27E031
+S27E032
+S28E015
+S28E016
+S28E017
+S28E018
+S28E019
+S28E020
+S28E021
+S28E022
+S28E023
+S28E024
+S28E025
+S28E026
+S28E027
+S28E028
+S28E029
+S28E030
+S28E031
+S28E032
+S29E015
+S29E016
+S29E017
+S29E018
+S29E019
+S29E020
+S29E021
+S29E022
+S29E023
+S29E024
+S29E025
+S29E026
+S29E027
+S29E028
+S29E029
+S29E030
+S29E031
+S29E032
+S30E016
+S30E017
+S30E018
+S30E019
+S30E020
+S30E021
+S30E022
+S30E023
+S30E024
+S30E025
+S30E026
+S30E027
+S30E028
+S30E029
+S30E030
+S30E031
+S31E017
+S31E018
+S31E019
+S31E020
+S31E021
+S31E022
+S31E023
+S31E024
+S31E025
+S31E026
+S31E027
+S31E028
+S31E029
+S31E030
+S32E017
+S32E018
+S32E019
+S32E020
+S32E021
+S32E022
+S32E023
+S32E024
+S32E025
+S32E026
+S32E027
+S32E028
+S32E029
+S32E030
+S33E017
+S33E018
+S33E019
+S33E020
+S33E021
+S33E022
+S33E023
+S33E024
+S33E025
+S33E026
+S33E027
+S33E028
+S33E029
+S34E017
+S34E018
+S34E019
+S34E020
+S34E021
+S34E022
+S34E023
+S34E024
+S34E025
+S34E026
+S34E027
+S35E018
+S35E019
+S35E020
+S35E021
+S35E022
+S35E023
+S35E024
+S35E025
+
diff --git a/tim/prune/function/srtm/srtmtiles.dat b/tim/prune/function/srtm/srtmtiles.dat
new file mode 100644 (file)
index 0000000..36ebbf5
Binary files /dev/null and b/tim/prune/function/srtm/srtmtiles.dat differ
index 5e31a4e97aee5086ba60d184bc69e6e6d276d0be..9cfd7cee703d9039bc4d520ab2888b0de89100ed 100644 (file)
@@ -22,6 +22,7 @@ import tim.prune.DataSubscriber;
 import tim.prune.FunctionLibrary;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
 import tim.prune.FunctionLibrary;
 import tim.prune.GenericFunction;
 import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.Coordinate;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.Coordinate;
@@ -214,8 +215,8 @@ public class DetailsDisplay extends GenericDisplay
                _distUnitsDropdown.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _distUnitsDropdown.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
-                               dataUpdated(DataSubscriber.UNITS_CHANGED);
                                Config.setConfigBoolean(Config.KEY_METRIC_UNITS, _distUnitsDropdown.getSelectedIndex() == 0);
                                Config.setConfigBoolean(Config.KEY_METRIC_UNITS, _distUnitsDropdown.getSelectedIndex() == 0);
+                               UpdateMessageBroker.informSubscribers(DataSubscriber.UNITS_CHANGED);
                        }
                });
                lowerPanel.add(_distUnitsDropdown);
                        }
                });
                lowerPanel.add(_distUnitsDropdown);
@@ -405,7 +406,12 @@ public class DetailsDisplay extends GenericDisplay
                        default: // just as it was
                                coord = inCoordinate.output(Coordinate.FORMAT_NONE);
                }
                        default: // just as it was
                                coord = inCoordinate.output(Coordinate.FORMAT_NONE);
                }
-               return inPrefix + coord;
+               // Fix broken degree signs (due to unicode mangling)
+               final char brokenDeg = 65533;
+               if (coord.indexOf(brokenDeg) >= 0) {
+                       coord = coord.replaceAll(String.valueOf(brokenDeg), "\u00B0");
+               }
+               return inPrefix + restrictDP(coord);
        }
 
 
        }
 
 
@@ -430,6 +436,25 @@ public class DetailsDisplay extends GenericDisplay
                return _distanceFormatter.format(inDist);
        }
 
                return _distanceFormatter.format(inDist);
        }
 
+       /**
+        * Restrict the given coordinate to a limited number of decimal places for display
+        * @param inCoord coordinate string
+        * @return chopped string
+        */
+       private static String restrictDP(String inCoord)
+       {
+               final int DECIMAL_PLACES = 7;
+               if (inCoord == null) return "";
+               final int dotPos = Math.max(inCoord.lastIndexOf('.'), inCoord.lastIndexOf(','));
+               if (dotPos >= 0) {
+                       final int chopPos = dotPos + DECIMAL_PLACES;
+                       if (chopPos < (inCoord.length()-1)) {
+                               return inCoord.substring(0, chopPos);
+                       }
+               }
+               return inCoord;
+       }
+
        /**
         * Create a little button for rotating the current photo
         * @param inIcon icon to use (from IconManager)
        /**
         * Create a little button for rotating the current photo
         * @param inIcon icon to use (from IconManager)
index f34afd724c20f199c28f029ef5b98d34ac877958..df706b74e17c754661ebc164b22a8adf2724b56c 100644 (file)
@@ -22,7 +22,7 @@ public abstract class DisplayUtils
                        + " " + ((inNumSecs / 60) % 60) + I18nManager.getText("display.range.time.mins");
                if (inNumSecs < 432000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days")
                        + " " + (inNumSecs / 60 / 60) % 24 + I18nManager.getText("display.range.time.hours");
                        + " " + ((inNumSecs / 60) % 60) + I18nManager.getText("display.range.time.mins");
                if (inNumSecs < 432000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days")
                        + " " + (inNumSecs / 60 / 60) % 24 + I18nManager.getText("display.range.time.hours");
-               if (inNumSecs < 8640000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days");
+               if (inNumSecs < 86400000L) return "" + (inNumSecs / 86400L) + I18nManager.getText("display.range.time.days");
                return "big";
        }
 }
                return "big";
        }
 }
diff --git a/tim/prune/gui/GenericChart.java b/tim/prune/gui/GenericChart.java
deleted file mode 100644 (file)
index ae2feac..0000000
+++ /dev/null
@@ -1,110 +0,0 @@
-package tim.prune.gui;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.event.MouseEvent;
-import java.awt.event.MouseListener;
-
-import tim.prune.I18nManager;
-import tim.prune.config.ColourScheme;
-import tim.prune.config.Config;
-import tim.prune.data.TrackInfo;
-
-
-/**
- * Generic chart component to form baseclass for map and profile charts
- */
-public abstract class GenericChart extends GenericDisplay implements MouseListener
-{
-       protected Dimension MINIMUM_SIZE = new Dimension(200, 250);
-       protected static final int BORDER_WIDTH = 8;
-
-       // Colours
-       private static final Color COLOR_NODATA_TEXT = Color.GRAY;
-
-
-       /**
-        * Constructor
-        * @param inTrackInfo track info object
-        */
-       protected GenericChart(TrackInfo inTrackInfo)
-       {
-               super(inTrackInfo);
-       }
-
-       /**
-        * Override minimum size method to restrict map
-        */
-       public Dimension getMinimumSize()
-       {
-               return MINIMUM_SIZE;
-       }
-
-       /**
-        * Override paint method to draw map
-        * @param inG graphics object
-        */
-       public void paint(Graphics inG)
-       {
-               super.paint(inG);
-               int width = getWidth();
-               int height = getHeight();
-               // Get colours
-               ColourScheme colourScheme = Config.getColourScheme();
-               final Color borderColour = colourScheme.getColour(ColourScheme.IDX_BORDERS);
-               final Color backgroundColour = colourScheme.getColour(ColourScheme.IDX_BACKGROUND);
-               final Color insideColour = backgroundColour;
-               // border background
-               inG.setColor(backgroundColour);
-               inG.fillRect(0, 0, width, height);
-               if (width < 2*BORDER_WIDTH || height < 2*BORDER_WIDTH) return;
-               // blank graph area, with line border
-               inG.setColor(insideColour);
-               inG.fillRect(BORDER_WIDTH, BORDER_WIDTH, width - 2*BORDER_WIDTH, height-2*BORDER_WIDTH);
-               // Display message if no data to be displayed
-               if (_track == null || _track.getNumPoints() <= 0)
-               {
-                       inG.setColor(COLOR_NODATA_TEXT);
-                       inG.drawString(I18nManager.getText("display.nodata"), 50, height/2);
-               }
-               else {
-                       inG.setColor(borderColour);
-                       inG.drawRect(BORDER_WIDTH, BORDER_WIDTH, width - 2*BORDER_WIDTH, height-2*BORDER_WIDTH);
-               }
-       }
-
-
-       /**
-        * Method to inform map that data has changed
-        */
-       public void dataUpdated(byte inUpdateType)
-       {
-               repaint();
-       }
-
-
-       /**
-        * mouse enter events ignored
-        */
-       public void mouseEntered(MouseEvent e)
-       {}
-
-       /**
-        * mouse exit events ignored
-        */
-       public void mouseExited(MouseEvent e)
-       {}
-
-       /**
-        * ignore mouse pressed for now too
-        */
-       public void mousePressed(MouseEvent e)
-       {}
-
-       /**
-        * and also ignore mouse released
-        */
-       public void mouseReleased(MouseEvent e)
-       {}
-}
index 998a533ce4a73f58c1ae43cb95a2e5af84a24b7a..1cca456e2271b5979b9e9e59355857521191d3e4 100644 (file)
@@ -1,8 +1,8 @@
 package tim.prune.gui;
 
 package tim.prune.gui;
 
+import java.awt.Toolkit;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
 import java.awt.event.ActionEvent;
 import java.awt.event.ActionListener;
-import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
 
 import javax.swing.JButton;
 import java.awt.event.KeyEvent;
 
 import javax.swing.JButton;
@@ -73,6 +73,7 @@ public class MenuManager implements DataSubscriber
        private JMenu     _browserMapMenu = null;
        private JMenuItem _chartItem = null;
        private JMenuItem _getGpsiesItem = null;
        private JMenu     _browserMapMenu = null;
        private JMenuItem _chartItem = null;
        private JMenuItem _getGpsiesItem = null;
+       private JMenuItem _lookupSrtmItem = null;
        private JMenuItem _distanceItem = null;
        private JMenuItem _fullRangeDetailsItem = null;
        private JMenuItem _saveExifItem = null;
        private JMenuItem _distanceItem = null;
        private JMenuItem _fullRangeDetailsItem = null;
        private JMenuItem _saveExifItem = null;
@@ -84,6 +85,7 @@ public class MenuManager implements DataSubscriber
        private JMenuItem _rotatePhotoLeft = null;
        private JMenuItem _rotatePhotoRight = null;
        private JMenuItem _ignoreExifThumb = null;
        private JMenuItem _rotatePhotoLeft = null;
        private JMenuItem _rotatePhotoRight = null;
        private JMenuItem _ignoreExifThumb = null;
+       private JCheckBoxMenuItem _onlineCheckbox = null;
 
        // ActionListeners for reuse by menu and toolbar
        private ActionListener _openFileAction = null;
 
        // ActionListeners for reuse by menu and toolbar
        private ActionListener _openFileAction = null;
@@ -140,7 +142,7 @@ public class MenuManager implements DataSubscriber
                JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
                setAltKey(fileMenu, "altkey.menu.file");
                // Open file
                JMenu fileMenu = new JMenu(I18nManager.getText("menu.file"));
                setAltKey(fileMenu, "altkey.menu.file");
                // Open file
-               JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("menu.file.open"));
+               JMenuItem openMenuItem = new JMenuItem(I18nManager.getText("function.open"));
                setShortcut(openMenuItem, "shortcut.menu.file.open");
                _openFileAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                setShortcut(openMenuItem, "shortcut.menu.file.open");
                _openFileAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
@@ -207,8 +209,8 @@ public class MenuManager implements DataSubscriber
                // Track menu
                JMenu trackMenu = new JMenu(I18nManager.getText("menu.track"));
                setAltKey(trackMenu, "altkey.menu.track");
                // Track menu
                JMenu trackMenu = new JMenu(I18nManager.getText("menu.track"));
                setAltKey(trackMenu, "altkey.menu.track");
-               _undoItem = new JMenuItem(I18nManager.getText("menu.edit.undo"));
-               setShortcut(_undoItem, "shortcut.menu.edit.undo");
+               _undoItem = new JMenuItem(I18nManager.getText("menu.track.undo"));
+               setShortcut(_undoItem, "shortcut.menu.track.undo");
                _undoAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _undoAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -218,7 +220,7 @@ public class MenuManager implements DataSubscriber
                _undoItem.addActionListener(_undoAction);
                _undoItem.setEnabled(false);
                trackMenu.add(_undoItem);
                _undoItem.addActionListener(_undoAction);
                _undoItem.setEnabled(false);
                trackMenu.add(_undoItem);
-               _clearUndoItem = new JMenuItem(I18nManager.getText("menu.edit.clearundo"));
+               _clearUndoItem = new JMenuItem(I18nManager.getText("menu.track.clearundo"));
                _clearUndoItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _clearUndoItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -232,7 +234,7 @@ public class MenuManager implements DataSubscriber
                setShortcut(_compressItem, "shortcut.menu.edit.compress");
                _compressItem.setEnabled(false);
                trackMenu.add(_compressItem);
                setShortcut(_compressItem, "shortcut.menu.edit.compress");
                _compressItem.setEnabled(false);
                trackMenu.add(_compressItem);
-               _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.edit.deletemarked"));
+               _deleteMarkedPointsItem = new JMenuItem(I18nManager.getText("menu.track.deletemarked"));
                _deleteMarkedPointsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _deleteMarkedPointsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -243,9 +245,9 @@ public class MenuManager implements DataSubscriber
                trackMenu.add(_deleteMarkedPointsItem);
                trackMenu.addSeparator();
                // Rearrange waypoints
                trackMenu.add(_deleteMarkedPointsItem);
                trackMenu.addSeparator();
                // Rearrange waypoints
-               _rearrangeMenu = new JMenu(I18nManager.getText("menu.edit.rearrange"));
+               _rearrangeMenu = new JMenu(I18nManager.getText("menu.track.rearrange"));
                _rearrangeMenu.setEnabled(false);
                _rearrangeMenu.setEnabled(false);
-               JMenuItem  rearrangeStartItem = new JMenuItem(I18nManager.getText("menu.edit.rearrange.start"));
+               JMenuItem  rearrangeStartItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.start"));
                rearrangeStartItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                rearrangeStartItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -254,7 +256,7 @@ public class MenuManager implements DataSubscriber
                });
                rearrangeStartItem.setEnabled(true);
                _rearrangeMenu.add(rearrangeStartItem);
                });
                rearrangeStartItem.setEnabled(true);
                _rearrangeMenu.add(rearrangeStartItem);
-               JMenuItem rearrangeEndItem = new JMenuItem(I18nManager.getText("menu.edit.rearrange.end"));
+               JMenuItem rearrangeEndItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.end"));
                rearrangeEndItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                rearrangeEndItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -263,7 +265,7 @@ public class MenuManager implements DataSubscriber
                });
                rearrangeEndItem.setEnabled(true);
                _rearrangeMenu.add(rearrangeEndItem);
                });
                rearrangeEndItem.setEnabled(true);
                _rearrangeMenu.add(rearrangeEndItem);
-               JMenuItem rearrangeNearestItem = new JMenuItem(I18nManager.getText("menu.edit.rearrange.nearest"));
+               JMenuItem rearrangeNearestItem = new JMenuItem(I18nManager.getText("menu.track.rearrange.nearest"));
                rearrangeNearestItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                rearrangeNearestItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -277,13 +279,16 @@ public class MenuManager implements DataSubscriber
                _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES);
                _getGpsiesItem.setEnabled(false);
                trackMenu.add(_getGpsiesItem);
                _getGpsiesItem = makeMenuItem(FunctionLibrary.FUNCTION_GET_GPSIES);
                _getGpsiesItem.setEnabled(false);
                trackMenu.add(_getGpsiesItem);
+               _lookupSrtmItem = makeMenuItem(FunctionLibrary.FUNCTION_LOOKUP_SRTM);
+               _lookupSrtmItem.setEnabled(false);
+               trackMenu.add(_lookupSrtmItem);
                menubar.add(trackMenu);
 
                // Range menu
                JMenu rangeMenu = new JMenu(I18nManager.getText("menu.range"));
                setAltKey(rangeMenu, "altkey.menu.range");
                menubar.add(trackMenu);
 
                // Range menu
                JMenu rangeMenu = new JMenu(I18nManager.getText("menu.range"));
                setAltKey(rangeMenu, "altkey.menu.range");
-               _selectAllItem = new JMenuItem(I18nManager.getText("menu.select.all"));
-               setShortcut(_selectAllItem, "shortcut.menu.select.all");
+               _selectAllItem = new JMenuItem(I18nManager.getText("menu.range.all"));
+               setShortcut(_selectAllItem, "shortcut.menu.range.all");
                _selectAllItem.setEnabled(false);
                _selectAllItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                _selectAllItem.setEnabled(false);
                _selectAllItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
@@ -292,7 +297,7 @@ public class MenuManager implements DataSubscriber
                        }
                });
                rangeMenu.add(_selectAllItem);
                        }
                });
                rangeMenu.add(_selectAllItem);
-               _selectNoneItem = new JMenuItem(I18nManager.getText("menu.select.none"));
+               _selectNoneItem = new JMenuItem(I18nManager.getText("menu.range.none"));
                _selectNoneItem.setEnabled(false);
                _selectNoneItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                _selectNoneItem.setEnabled(false);
                _selectNoneItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
@@ -302,7 +307,7 @@ public class MenuManager implements DataSubscriber
                });
                rangeMenu.add(_selectNoneItem);
                rangeMenu.addSeparator();
                });
                rangeMenu.add(_selectNoneItem);
                rangeMenu.addSeparator();
-               _selectStartItem = new JMenuItem(I18nManager.getText("menu.select.start"));
+               _selectStartItem = new JMenuItem(I18nManager.getText("menu.range.start"));
                _selectStartItem.setEnabled(false);
                _selectStartAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                _selectStartItem.setEnabled(false);
                _selectStartAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
@@ -312,7 +317,7 @@ public class MenuManager implements DataSubscriber
                };
                _selectStartItem.addActionListener(_selectStartAction);
                rangeMenu.add(_selectStartItem);
                };
                _selectStartItem.addActionListener(_selectStartAction);
                rangeMenu.add(_selectStartItem);
-               _selectEndItem = new JMenuItem(I18nManager.getText("menu.select.end"));
+               _selectEndItem = new JMenuItem(I18nManager.getText("menu.range.end"));
                _selectEndItem.setEnabled(false);
                _selectEndAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                _selectEndItem.setEnabled(false);
                _selectEndAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
@@ -323,7 +328,7 @@ public class MenuManager implements DataSubscriber
                _selectEndItem.addActionListener(_selectEndAction);
                rangeMenu.add(_selectEndItem);
                rangeMenu.addSeparator();
                _selectEndItem.addActionListener(_selectEndAction);
                rangeMenu.add(_selectEndItem);
                rangeMenu.addSeparator();
-               _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.edit.deleterange"));
+               _deleteRangeItem = new JMenuItem(I18nManager.getText("menu.range.deleterange"));
                _deleteRangeAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _deleteRangeAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -333,7 +338,7 @@ public class MenuManager implements DataSubscriber
                _deleteRangeItem.addActionListener(_deleteRangeAction);
                _deleteRangeItem.setEnabled(false);
                rangeMenu.add(_deleteRangeItem);
                _deleteRangeItem.addActionListener(_deleteRangeAction);
                _deleteRangeItem.setEnabled(false);
                rangeMenu.add(_deleteRangeItem);
-               _reverseItem = new JMenuItem(I18nManager.getText("menu.edit.reverse"));
+               _reverseItem = new JMenuItem(I18nManager.getText("menu.range.reverse"));
                _reverseItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _reverseItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -348,7 +353,7 @@ public class MenuManager implements DataSubscriber
                _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET);
                _addAltitudeOffsetItem.setEnabled(false);
                rangeMenu.add(_addAltitudeOffsetItem);
                _addAltitudeOffsetItem = makeMenuItem(FunctionLibrary.FUNCTION_ADD_ALTITUDE_OFFSET);
                _addAltitudeOffsetItem.setEnabled(false);
                rangeMenu.add(_addAltitudeOffsetItem);
-               _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.edit.mergetracksegments"));
+               _mergeSegmentsItem = new JMenuItem(I18nManager.getText("menu.range.mergetracksegments"));
                _mergeSegmentsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _mergeSegmentsItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -358,7 +363,7 @@ public class MenuManager implements DataSubscriber
                _mergeSegmentsItem.setEnabled(false);
                rangeMenu.add(_mergeSegmentsItem);
                rangeMenu.addSeparator();
                _mergeSegmentsItem.setEnabled(false);
                rangeMenu.add(_mergeSegmentsItem);
                rangeMenu.addSeparator();
-               _interpolateItem = new JMenuItem(I18nManager.getText("menu.edit.interpolate"));
+               _interpolateItem = new JMenuItem(I18nManager.getText("menu.range.interpolate"));
                _interpolateItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _interpolateItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -367,7 +372,7 @@ public class MenuManager implements DataSubscriber
                });
                _interpolateItem.setEnabled(false);
                rangeMenu.add(_interpolateItem);
                });
                _interpolateItem.setEnabled(false);
                rangeMenu.add(_interpolateItem);
-               _averageItem = new JMenuItem(I18nManager.getText("menu.edit.average"));
+               _averageItem = new JMenuItem(I18nManager.getText("menu.range.average"));
                _averageItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _averageItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -376,7 +381,7 @@ public class MenuManager implements DataSubscriber
                });
                _averageItem.setEnabled(false);
                rangeMenu.add(_averageItem);
                });
                _averageItem.setEnabled(false);
                rangeMenu.add(_averageItem);
-               _cutAndMoveItem = new JMenuItem(I18nManager.getText("menu.edit.cutandmove"));
+               _cutAndMoveItem = new JMenuItem(I18nManager.getText("menu.range.cutandmove"));
                _cutAndMoveItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _cutAndMoveItem.addActionListener(new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -393,7 +398,7 @@ public class MenuManager implements DataSubscriber
                // Point menu
                JMenu pointMenu = new JMenu(I18nManager.getText("menu.point"));
                setAltKey(pointMenu, "altkey.menu.point");
                // Point menu
                JMenu pointMenu = new JMenu(I18nManager.getText("menu.point"));
                setAltKey(pointMenu, "altkey.menu.point");
-               _editPointItem = new JMenuItem(I18nManager.getText("menu.edit.editpoint"));
+               _editPointItem = new JMenuItem(I18nManager.getText("menu.point.editpoint"));
                _editPointAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _editPointAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -406,7 +411,7 @@ public class MenuManager implements DataSubscriber
                _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME);
                _editWaypointNameItem.setEnabled(false);
                pointMenu.add(_editWaypointNameItem);
                _editWaypointNameItem = makeMenuItem(FunctionLibrary.FUNCTION_EDIT_WAYPOINT_NAME);
                _editWaypointNameItem.setEnabled(false);
                pointMenu.add(_editWaypointNameItem);
-               _deletePointItem = new JMenuItem(I18nManager.getText("menu.edit.deletepoint"));
+               _deletePointItem = new JMenuItem(I18nManager.getText("menu.point.deletepoint"));
                _deletePointAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
                _deletePointAction = new ActionListener() {
                        public void actionPerformed(ActionEvent e)
                        {
@@ -415,6 +420,7 @@ public class MenuManager implements DataSubscriber
                };
                _deletePointItem.addActionListener(_deletePointAction);
                _deletePointItem.setEnabled(false);
                };
                _deletePointItem.addActionListener(_deletePointAction);
                _deletePointItem.setEnabled(false);
+               _deletePointItem.setAccelerator(KeyStroke.getKeyStroke(KeyEvent.VK_DELETE, 0));
                pointMenu.add(_deletePointItem);
                pointMenu.addSeparator();
                // find a waypoint
                pointMenu.add(_deletePointItem);
                pointMenu.addSeparator();
                // find a waypoint
@@ -576,22 +582,29 @@ public class MenuManager implements DataSubscriber
                // Set the map background
                JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
                settingsMenu.add(mapBgItem);
                // Set the map background
                JMenuItem mapBgItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_MAP_BG);
                settingsMenu.add(mapBgItem);
+               _onlineCheckbox = new JCheckBoxMenuItem(I18nManager.getText("menu.settings.onlinemode"));
+               _onlineCheckbox.setSelected(Config.getConfigBoolean(Config.KEY_ONLINE_MODE));
+               _onlineCheckbox.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e) {
+                               boolean isOnline = _onlineCheckbox.isSelected();
+                               Config.setConfigBoolean(Config.KEY_ONLINE_MODE, isOnline);
+                               if (isOnline) {UpdateMessageBroker.informSubscribers();}
+                       }
+               });
+               settingsMenu.add(_onlineCheckbox);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_DISK_CACHE));
+               settingsMenu.addSeparator();
                // Set kmz image size
                // Set kmz image size
-               JMenuItem setKmzImageSizeItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE);
-               settingsMenu.add(setKmzImageSizeItem);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_KMZ_IMAGE_SIZE));
                // Set program paths
                // Set program paths
-               JMenuItem setPathsItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS);
-               settingsMenu.add(setPathsItem);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_PATHS));
                // Set colours
                // Set colours
-               JMenuItem setColoursItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS);
-               settingsMenu.add(setColoursItem);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_COLOURS));
                // Set language
                // Set language
-               JMenuItem setLanguageItem = makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE);
-               settingsMenu.add(setLanguageItem);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SET_LANGUAGE));
                settingsMenu.addSeparator();
                // Save configuration
                settingsMenu.addSeparator();
                // Save configuration
-               JMenuItem saveConfigMenuItem = makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG);
-               settingsMenu.add(saveConfigMenuItem);
+               settingsMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SAVECONFIG));
                menubar.add(settingsMenu);
 
                // Help menu
                menubar.add(settingsMenu);
 
                // Help menu
@@ -600,12 +613,9 @@ public class MenuManager implements DataSubscriber
                JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
                setShortcut(helpItem, "shortcut.menu.help.help");
                helpMenu.add(helpItem);
                JMenuItem helpItem = makeMenuItem(FunctionLibrary.FUNCTION_HELP);
                setShortcut(helpItem, "shortcut.menu.help.help");
                helpMenu.add(helpItem);
-               JMenuItem showKeysItem = makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS);
-               helpMenu.add(showKeysItem);
-               JMenuItem aboutItem = makeMenuItem(FunctionLibrary.FUNCTION_ABOUT);
-               helpMenu.add(aboutItem);
-               JMenuItem checkVersionItem = makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION);
-               helpMenu.add(checkVersionItem);
+               helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_SHOW_KEYS));
+               helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_ABOUT));
+               helpMenu.add(makeMenuItem(FunctionLibrary.FUNCTION_CHECK_VERSION));
                menubar.add(helpMenu);
 
                return menubar;
                menubar.add(helpMenu);
 
                return menubar;
@@ -658,7 +668,9 @@ public class MenuManager implements DataSubscriber
                        if (code >= 0 && code < 26)
                        {
                                // Found a valid code between A and Z
                        if (code >= 0 && code < 26)
                        {
                                // Found a valid code between A and Z
-                               inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code], InputEvent.CTRL_DOWN_MASK));
+                               inMenuItem.setAccelerator(KeyStroke.getKeyStroke(KEY_EVENTS[code],
+                                       Toolkit.getDefaultToolkit().getMenuShortcutKeyMask()));
+                               // use platform-specific key mask so Ctrl on Linux/Win, Clover on Mac
                        }
                }
        }
                        }
                }
        }
@@ -672,7 +684,7 @@ public class MenuManager implements DataSubscriber
                JToolBar toolbar = new JToolBar();
                // Add text file
                JButton openFileButton = new JButton(IconManager.getImageIcon(IconManager.OPEN_FILE));
                JToolBar toolbar = new JToolBar();
                // Add text file
                JButton openFileButton = new JButton(IconManager.getImageIcon(IconManager.OPEN_FILE));
-               openFileButton.setToolTipText(I18nManager.getText("menu.file.open"));
+               openFileButton.setToolTipText(I18nManager.getText("function.open"));
                openFileButton.addActionListener(_openFileAction);
                toolbar.add(openFileButton);
                // Add photo
                openFileButton.addActionListener(_openFileAction);
                toolbar.add(openFileButton);
                // Add photo
@@ -688,36 +700,36 @@ public class MenuManager implements DataSubscriber
                toolbar.add(_saveButton);
                // Undo
                _undoButton = new JButton(IconManager.getImageIcon(IconManager.UNDO));
                toolbar.add(_saveButton);
                // Undo
                _undoButton = new JButton(IconManager.getImageIcon(IconManager.UNDO));
-               _undoButton.setToolTipText(I18nManager.getText("menu.edit.undo"));
+               _undoButton.setToolTipText(I18nManager.getText("menu.track.undo"));
                _undoButton.addActionListener(_undoAction);
                _undoButton.setEnabled(false);
                toolbar.add(_undoButton);
                // Edit point
                _editPointButton = new JButton(IconManager.getImageIcon(IconManager.EDIT_POINT));
                _undoButton.addActionListener(_undoAction);
                _undoButton.setEnabled(false);
                toolbar.add(_undoButton);
                // Edit point
                _editPointButton = new JButton(IconManager.getImageIcon(IconManager.EDIT_POINT));
-               _editPointButton.setToolTipText(I18nManager.getText("menu.edit.editpoint"));
+               _editPointButton.setToolTipText(I18nManager.getText("menu.point.editpoint"));
                _editPointButton.addActionListener(_editPointAction);
                _editPointButton.setEnabled(false);
                toolbar.add(_editPointButton);
                // Delete point
                _deletePointButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_POINT));
                _editPointButton.addActionListener(_editPointAction);
                _editPointButton.setEnabled(false);
                toolbar.add(_editPointButton);
                // Delete point
                _deletePointButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_POINT));
-               _deletePointButton.setToolTipText(I18nManager.getText("menu.edit.deletepoint"));
+               _deletePointButton.setToolTipText(I18nManager.getText("menu.point.deletepoint"));
                _deletePointButton.addActionListener(_deletePointAction);
                _deletePointButton.setEnabled(false);
                toolbar.add(_deletePointButton);
                // Delete range
                _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
                _deletePointButton.addActionListener(_deletePointAction);
                _deletePointButton.setEnabled(false);
                toolbar.add(_deletePointButton);
                // Delete range
                _deleteRangeButton = new JButton(IconManager.getImageIcon(IconManager.DELETE_RANGE));
-               _deleteRangeButton.setToolTipText(I18nManager.getText("menu.edit.deleterange"));
+               _deleteRangeButton.setToolTipText(I18nManager.getText("menu.range.deleterange"));
                _deleteRangeButton.addActionListener(_deleteRangeAction);
                _deleteRangeButton.setEnabled(false);
                toolbar.add(_deleteRangeButton);
                // Select start, end
                _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
                _deleteRangeButton.addActionListener(_deleteRangeAction);
                _deleteRangeButton.setEnabled(false);
                toolbar.add(_deleteRangeButton);
                // Select start, end
                _selectStartButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_START));
-               _selectStartButton.setToolTipText(I18nManager.getText("menu.select.start"));
+               _selectStartButton.setToolTipText(I18nManager.getText("menu.range.start"));
                _selectStartButton.addActionListener(_selectStartAction);
                _selectStartButton.setEnabled(false);
                toolbar.add(_selectStartButton);
                _selectEndButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_END));
                _selectStartButton.addActionListener(_selectStartAction);
                _selectStartButton.setEnabled(false);
                toolbar.add(_selectStartButton);
                _selectEndButton = new JButton(IconManager.getImageIcon(IconManager.SET_RANGE_END));
-               _selectEndButton.setToolTipText(I18nManager.getText("menu.select.end"));
+               _selectEndButton.setToolTipText(I18nManager.getText("menu.range.end"));
                _selectEndButton.addActionListener(_selectEndAction);
                _selectEndButton.setEnabled(false);
                toolbar.add(_selectEndButton);
                _selectEndButton.addActionListener(_selectEndAction);
                _selectEndButton.setEnabled(false);
                toolbar.add(_selectEndButton);
@@ -769,6 +781,7 @@ public class MenuManager implements DataSubscriber
                _browserMapMenu.setEnabled(hasData);
                _distanceItem.setEnabled(hasData);
                _getGpsiesItem.setEnabled(hasData);
                _browserMapMenu.setEnabled(hasData);
                _distanceItem.setEnabled(hasData);
                _getGpsiesItem.setEnabled(hasData);
+               _lookupSrtmItem.setEnabled(hasData);
                _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
                // is undo available?
                boolean hasUndo = !_app.getUndoStack().isEmpty();
                _findWaypointItem.setEnabled(hasData && _track.hasWaypoints());
                // is undo available?
                boolean hasUndo = !_app.getUndoStack().isEmpty();
index 101f1a39c64aefcada6069c146765d4938ce3f34..88e77ca58ce6795986185604435eb59e317a6b8e 100644 (file)
@@ -19,6 +19,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
        private Photo _photo = null;
        private BufferedImage _thumbnail = null;
        private boolean _loadingImage = false;
        private Photo _photo = null;
        private BufferedImage _thumbnail = null;
        private boolean _loadingImage = false;
+       private boolean _loadFailed = false;
        /** String to show before photo is loaded */
        private static final String LOADING_STRING = I18nManager.getText("details.photo.loading") + " ...";
 
        /** String to show before photo is loaded */
        private static final String LOADING_STRING = I18nManager.getText("details.photo.loading") + " ...";
 
@@ -42,6 +43,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
                if (_photo != inPhoto) {
                        _photo = inPhoto;
                        _thumbnail = null;
                if (_photo != inPhoto) {
                        _photo = inPhoto;
                        _thumbnail = null;
+                       _loadFailed = false;
                }
                repaint();
        }
                }
                repaint();
        }
@@ -51,6 +53,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
         */
        public void refresh() {
                _thumbnail = null;
         */
        public void refresh() {
                _thumbnail = null;
+               _loadFailed = false;
        }
 
        /**
        }
 
        /**
@@ -63,7 +66,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
                if (_photo != null)
                {
                        // read thumbnail in separate thread
                if (_photo != null)
                {
                        // read thumbnail in separate thread
-                       if (_thumbnail == null && !_loadingImage)
+                       if (_thumbnail == null && !_loadingImage && !_loadFailed)
                        {
                                _loadingImage = true;
                                new Thread(this).start();
                        {
                                _loadingImage = true;
                                new Thread(this).start();
@@ -74,7 +77,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
                                inG.setColor(Color.BLACK);
                                inG.drawString(LOADING_STRING, 10, 30);
                        }
                                inG.setColor(Color.BLACK);
                                inG.drawString(LOADING_STRING, 10, 30);
                        }
-                       else
+                       else if (_thumbnail != null && !_loadFailed)
                        {
                                // Copy scaled, smoothed (and rotated) image into scaled
                                int usableWidth = getParent().getWidth()-10;
                        {
                                // Copy scaled, smoothed (and rotated) image into scaled
                                int usableWidth = getParent().getWidth()-10;
@@ -124,6 +127,7 @@ public class PhotoThumbnail extends JPanel implements Runnable
                                _thumbnail = ImageUtils.createScaledImage(image, thumbSize.width, thumbSize.height);
                                image = null;
                        }
                                _thumbnail = ImageUtils.createScaledImage(image, thumbSize.width, thumbSize.height);
                                image = null;
                        }
+                       else _loadFailed = true;
                }
                _loadingImage = false;
                repaint();
                }
                _loadingImage = false;
                repaint();
diff --git a/tim/prune/gui/ProfileChart.java b/tim/prune/gui/ProfileChart.java
deleted file mode 100644 (file)
index 7c7b4c5..0000000
+++ /dev/null
@@ -1,242 +0,0 @@
-package tim.prune.gui;
-
-import java.awt.Color;
-import java.awt.Dimension;
-import java.awt.Graphics;
-import java.awt.event.MouseEvent;
-
-import tim.prune.I18nManager;
-import tim.prune.config.ColourScheme;
-import tim.prune.config.Config;
-import tim.prune.data.Altitude;
-import tim.prune.data.AltitudeRange;
-import tim.prune.data.Track;
-import tim.prune.data.TrackInfo;
-
-/**
- * Chart component for the profile display
- */
-public class ProfileChart extends GenericChart
-{
-       /** Current scale factor in x direction*/
-       private double _xScaleFactor = 0.0;
-       /** Possible altitude scales to use */
-       private static final int[] ALTITUDE_SCALES = {10000, 5000, 2000, 1000, 500, 200, 100, 50};
-
-
-       /**
-        * Constructor
-        * @param inTrackInfo Track info object
-        */
-       public ProfileChart(TrackInfo inTrackInfo)
-       {
-               super(inTrackInfo);
-               MINIMUM_SIZE = new Dimension(200, 100);
-               addMouseListener(this);
-       }
-
-
-       /**
-        * Override paint method to draw map
-        * @param g Graphics object
-        */
-       public void paint(Graphics g)
-       {
-               super.paint(g);
-               if (_track != null && _track.getNumPoints() > 0)
-               {
-                       int width = getWidth();
-                       int height = getHeight();
-
-                       // Set up colours
-                       final Color barColour = Config.getColourScheme().getColour(ColourScheme.IDX_POINT);
-                       final Color rangeColour = Config.getColourScheme().getColour(ColourScheme.IDX_SELECTION);
-                       final Color currentColour = Config.getColourScheme().getColour(ColourScheme.IDX_PRIMARY);
-                       final Color secondColour = Config.getColourScheme().getColour(ColourScheme.IDX_SECONDARY);
-                       final Color lineColour = Config.getColourScheme().getColour(ColourScheme.IDX_LINES);
-
-                       // message if no altitudes in track
-                       if (!_track.hasAltitudeData())
-                       {
-                               g.setColor(lineColour);
-                               g.drawString(I18nManager.getText("display.noaltitudes"), 50, height/2);
-                               return;
-                       }
-
-                       // altitude profile
-                       AltitudeRange altitudeRange = _track.getAltitudeRange();
-                       int minAltitude = altitudeRange.getMinimum();
-                       int maxAltitude = altitudeRange.getMaximum();
-                       int numPoints = _track.getNumPoints();
-                       _xScaleFactor = 1.0 * (width - 2 * BORDER_WIDTH - 1) / numPoints;
-                       double yScaleFactor = 1.0 * (height - 2 * BORDER_WIDTH) / (maxAltitude - minAltitude);
-                       int barWidth = (int) (_xScaleFactor + 1.0);
-                       int selectedPoint = _trackInfo.getSelection().getCurrentPointIndex();
-                       // selection start, end
-                       int selectionStart = -1, selectionEnd = -1;
-                       if (_trackInfo.getSelection().hasRangeSelected()) {
-                               selectionStart = _trackInfo.getSelection().getStart();
-                               selectionEnd = _trackInfo.getSelection().getEnd();
-                       }
-
-                       // horizontal lines for scale - set to round numbers eg 500m
-                       int lineScale = getLineScale(minAltitude, maxAltitude);
-                       int altitude = 0;
-                       int x = 0, y = 0;
-                       if (lineScale > 1)
-                       {
-                               g.setColor(lineColour);
-                               while (altitude < maxAltitude)
-                               {
-                                       if (altitude > minAltitude)
-                                       {
-                                               y = height - BORDER_WIDTH - (int) (yScaleFactor * (altitude - minAltitude));
-                                               g.drawLine(BORDER_WIDTH + 1, y, width - BORDER_WIDTH - 1, y);
-                                       }
-                                       altitude += lineScale;
-                               }
-                       }
-
-                       try
-                       {
-                               // loop through points
-                               Altitude.Format chartFormat = altitudeRange.getFormat();
-                               g.setColor(barColour);
-                               for (int p = 0; p < numPoints; p++)
-                               {
-                                       x = (int) (_xScaleFactor * p) + 1;
-                                       if (p == selectionStart)
-                                               g.setColor(rangeColour);
-                                       else if (p == (selectionEnd+1))
-                                               g.setColor(barColour);
-                                       if (_track.getPoint(p).getAltitude().isValid())
-                                       {
-                                               altitude = _track.getPoint(p).getAltitude().getValue(chartFormat);
-                                               y = (int) (yScaleFactor * (altitude - minAltitude));
-                                               g.fillRect(BORDER_WIDTH+x, height-BORDER_WIDTH - y, barWidth, y);
-                                       }
-                               }
-                               // current point (make sure it's drawn last)
-                               if (selectedPoint > -1)
-                               {
-                                       Altitude alt = _track.getPoint(selectedPoint).getAltitude();
-                                       if (alt.isValid())
-                                       {
-                                               x = (int) (_xScaleFactor * selectedPoint) + 1;
-                                               g.setColor(secondColour);
-                                               g.fillRect(BORDER_WIDTH + x, BORDER_WIDTH+1, barWidth, height-2*BORDER_WIDTH-2);
-                                               g.setColor(currentColour);
-                                               altitude = alt.getValue(chartFormat);
-                                               y = (int) (yScaleFactor * (altitude - minAltitude));
-                                               g.fillRect(BORDER_WIDTH + x, height-BORDER_WIDTH - y, barWidth, y);
-                                       }
-                               }
-                       }
-                       catch (NullPointerException npe) { // ignore, probably due to data being changed
-                       }
-                       // Draw numbers on top of the graph to mark scale
-                       if (lineScale > 1)
-                       {
-                               int textHeight = g.getFontMetrics().getHeight();
-                               altitude = 0;
-                               y = 0;
-                               g.setColor(currentColour);
-                               while (altitude < maxAltitude)
-                               {
-                                       if (altitude > minAltitude)
-                                       {
-                                               y = height - BORDER_WIDTH - (int) (yScaleFactor * (altitude - minAltitude));
-                                               // Limit y so String isn't above border
-                                               if (y < (BORDER_WIDTH + textHeight))
-                                               {
-                                                       y = BORDER_WIDTH + textHeight;
-                                               }
-                                               g.drawString(""+altitude, BORDER_WIDTH + 5, y);
-                                       }
-                                       altitude += lineScale;
-                               }
-                       }
-               }
-       }
-
-
-       /**
-        * Work out the scale for the horizontal lines
-        * @param inMin min altitude of data
-        * @param inMax max altitude of data
-        * @return scale separation, or -1 for no scale
-        */
-       private int getLineScale(int inMin, int inMax)
-       {
-               if ((inMax - inMin) < 50 || inMax < 0)
-               {
-                       return -1;
-               }
-               int numScales = ALTITUDE_SCALES.length;
-               int scale = 0;
-               int numLines = 0;
-               int altitude = 0;
-               for (int i=0; i<numScales; i++)
-               {
-                       scale = ALTITUDE_SCALES[i];
-                       if (scale < inMax)
-                       {
-                               numLines = 0;
-                               altitude = 0;
-                               while (altitude < inMax)
-                               {
-                                       altitude += scale;
-                                       if (altitude > inMin)
-                                       {
-                                               numLines++;
-                                       }
-                               }
-                               if (numLines > 2)
-                               {
-                                       return scale;
-                               }
-                       }
-               }
-               // no suitable scale found so just use minimum
-               return ALTITUDE_SCALES[numScales-1];
-       }
-
-
-       /**
-        * Method to inform map that data has changed
-        * @param inTrack track object
-        */
-       public void dataUpdated(Track inTrack)
-       {
-               _track = inTrack;
-               repaint();
-       }
-
-
-       /**
-        * React to click on profile display
-        */
-       public void mouseClicked(MouseEvent e)
-       {
-               // ignore right clicks
-               if (_track != null && !e.isMetaDown())
-               {
-                       int xClick = e.getX();
-                       int yClick = e.getY();
-                       // Check click is within main area (not in border)
-                       if (xClick > BORDER_WIDTH && yClick > BORDER_WIDTH && xClick < (getWidth() - BORDER_WIDTH)
-                               && yClick < (getHeight() - BORDER_WIDTH))
-                       {
-                               // work out which data point is nearest and select it
-                               int pointNum = (int) ((e.getX() - BORDER_WIDTH) / _xScaleFactor);
-                               // If shift clicked, then extend selection
-                               if (e.isShiftDown()) {
-                                       _trackInfo.extendSelection(pointNum);
-                               }
-                               else {
-                                       _trackInfo.selectPoint(pointNum);
-                               }
-                       }
-               }
-       }
-}
diff --git a/tim/prune/gui/map/CloudmadeMapSource.java b/tim/prune/gui/map/CloudmadeMapSource.java
new file mode 100644 (file)
index 0000000..0cc9b77
--- /dev/null
@@ -0,0 +1,53 @@
+package tim.prune.gui.map;
+
+/**
+ * Class to act as a source for Cloudmade maps with a given style
+ */
+public class CloudmadeMapSource extends OsmMapSource
+{
+       /** Selected style number */
+       private String _style = null;
+       /** Server prefix including API-key unique to Prune application */
+       private static final String SERVER_PREFIX = "tile.cloudmade.com/03d86b66f51f4a3b8c236ac06f2a2e57/";
+
+       /**
+        * Constructor
+        * @param inName name to use for map source
+        * @param inStyle style, given as integer
+        * @param inMaxZoom maximum zoom level, 18 by default
+        */
+       public CloudmadeMapSource(String inName, String inStyle, int inMaxZoom)
+       {
+               // Note: Could check style for valid integer value here
+               super(inName, SERVER_PREFIX + inStyle + "/256/", null, inMaxZoom);
+               _style = inStyle;
+       }
+
+       /**
+        * @return semicolon-separated list of all fields
+        */
+       public String getConfigString()
+       {
+               return "c:" +  getName() + ";" + _style + ";" + getMaxZoomLevel();
+       }
+
+       /**
+        * Construct a new map source from its config string
+        * @param inConfigString string from Config, separated by semicolons
+        * @return new map source, or null if not parseable
+        */
+       public static CloudmadeMapSource fromConfig(String inConfigString)
+       {
+               CloudmadeMapSource source = null;
+               if (inConfigString.startsWith("c:"))
+               {
+                       String[] items = inConfigString.substring(2).split(";");
+                       try {
+                               if (items.length == 3) {
+                                       source = new CloudmadeMapSource(items[0], items[1], Integer.parseInt(items[2]));
+                               }
+                       } catch (NumberFormatException nfe) {}
+               }
+               return source;
+       }
+}
diff --git a/tim/prune/gui/map/DiskTileCacher.java b/tim/prune/gui/map/DiskTileCacher.java
new file mode 100644 (file)
index 0000000..dfc4f92
--- /dev/null
@@ -0,0 +1,151 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.ImageObserver;
+import java.io.File;
+import java.io.FileOutputStream;
+import java.io.IOException;
+import java.io.InputStream;
+import java.net.URL;
+
+/**
+ * Class to control the reading and saving of map tiles
+ * to a cache on disk
+ */
+public class DiskTileCacher implements Runnable
+{
+       /** URL to get image from */
+       private URL _url = null;
+       /** File to save image to */
+       private File _file = null;
+       /** Observer to be notified */
+       private ImageObserver _observer = null;
+       /** Time limit to cache images for */
+       private static final long CACHE_TIME_LIMIT = 20 * 24 * 60 * 60 * 1000; // 20 days in ms
+
+       /**
+        * Private constructor
+        * @param inUrl URL to get
+        * @param inFile file to save to
+        */
+       private DiskTileCacher(URL inUrl, File inFile, ImageObserver inObserver)
+       {
+               _url = inUrl;
+               _file = inFile;
+               _observer = inObserver;
+               new Thread(this).start();
+       }
+
+       /**
+        * Get the specified tile from the disk cache
+        * @param inBasePath base path to whole disk cache
+        * @param inTilePath relative path to requested tile
+        * @param inCheckAge true to check age of file, false to ignore
+        * @return tile image if available, or null if not there
+        */
+       public static Image getTile(String inBasePath, String inTilePath, boolean inCheckAge)
+       {
+               if (inBasePath == null) {return null;}
+               File tileFile = new File(inBasePath, inTilePath);
+               Image image = null;
+               if (tileFile.exists() && tileFile.canRead() && tileFile.length() > 0) {
+                       long fileStamp = tileFile.lastModified();
+                       if (!inCheckAge || ((System.currentTimeMillis()-fileStamp) < CACHE_TIME_LIMIT))
+                       {
+                               try {
+                                       image = Toolkit.getDefaultToolkit().createImage(tileFile.getAbsolutePath());
+                               }
+                               catch (Exception e) {}
+                       }
+               }
+               return image;
+       }
+
+       /**
+        * Save the specified image tile to disk
+        * @param inUrl url to get image from
+        * @param inBasePath base path to disk cache
+        * @param inTilePath relative path to this tile
+        * @param inObserver observer to inform when load complete
+        */
+       public static void saveTile(URL inUrl, String inBasePath, String inTilePath, ImageObserver inObserver)
+       {
+               if (inBasePath == null || inTilePath == null) {return;}
+               // save file if possible
+               File basePath = new File(inBasePath);
+               if (!basePath.exists() || !basePath.isDirectory() || !basePath.canWrite()) {
+                       //System.err.println("Can't write");
+                       // Can't write to base path
+                       return;
+               }
+               File tileFile = new File(basePath, inTilePath);
+               // Check if this file is already being loaded
+               if (!isBeingLoaded(tileFile))
+               {
+                       File dir = tileFile.getParentFile();
+                       // Start a new thread to load the image if necessary
+                       if (dir.exists() || dir.mkdirs())
+                       {
+                               new DiskTileCacher(inUrl, tileFile, inObserver);
+                       }
+               }
+       }
+
+       /**
+        * Check whether the given tile is already being loaded
+        * @param inFile desired file
+        * @return true if temporary file with this name exists
+        */
+       private static boolean isBeingLoaded(File inFile)
+       {
+               File tempFile = new File(inFile.getAbsolutePath() + ".temp");
+               return tempFile.exists();
+       }
+
+       /**
+        * Run method for loading URL asynchronously and saving to file
+        */
+       public void run()
+       {
+               boolean finished = false;
+               InputStream in = null;
+               FileOutputStream out = null;
+               File tempFile = new File(_file.getAbsolutePath() + ".temp");
+               // Use a synchronized block across all threads to make sure this url is only fetched once
+               synchronized (DiskTileCacher.class) {
+                       if (tempFile.exists()) {return;}
+                       try {
+                               if (!tempFile.createNewFile()) {return;}
+                       }
+                       catch (Exception e) {return;}
+               }
+               try {
+                       // Open streams from URL and to file
+                       out = new FileOutputStream(tempFile);
+                       in = _url.openStream();
+                       int d = 0;
+                       // Loop over each byte in the stream (maybe buffering is more efficient?)
+                       while ((d = in.read()) >= 0) {
+                               out.write(d);
+                       }
+                       finished = true;
+               } catch (IOException e) {}
+               finally {
+                       try {
+                               in.close();
+                               out.close();
+                               if (!finished) {tempFile.delete();}
+                       }
+                       catch (Exception e) {} // ignore
+               }
+               // Move temp file to desired file location
+               if (!tempFile.renameTo(_file)) {
+                       // File couldn't be moved - delete both to be sure
+                       tempFile.delete();
+                       _file.delete();
+               }
+               // Tell parent that load is finished (parameters ignored)
+               _observer.imageUpdate(null, ImageObserver.ALLBITS, 0, 0, 0, 0);
+       }
+}
index d2f36ce165b45cfd5c315da68c6a70b5726a1f51..2717fcb66952417dc90189a95b49e75a963bc437 100644 (file)
@@ -40,6 +40,7 @@ import tim.prune.I18nManager;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.ColourScheme;
 import tim.prune.config.Config;
 import tim.prune.UpdateMessageBroker;
 import tim.prune.config.ColourScheme;
 import tim.prune.config.Config;
+import tim.prune.data.Checker;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
 import tim.prune.data.DoubleRange;
 import tim.prune.data.Coordinate;
 import tim.prune.data.DataPoint;
 import tim.prune.data.DoubleRange;
@@ -66,8 +67,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        private Selection _selection = null;
        /** Previously selected point */
        private int _prevSelectedPoint = -1;
        private Selection _selection = null;
        /** Previously selected point */
        private int _prevSelectedPoint = -1;
-       /** Tile cacher */
-       private MapTileCacher _tileCacher = new MapTileCacher(this);
+       /** Tile manager */
+       private MapTileManager _tileManager = new MapTileManager(this);
        /** Image to display */
        private BufferedImage _mapImage = null;
        /** Slider for transparency */
        /** Image to display */
        private BufferedImage _mapImage = null;
        /** Slider for transparency */
@@ -153,7 +154,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                ItemListener mapCheckListener = new ItemListener() {
                        public void itemStateChanged(ItemEvent e)
                        {
                ItemListener mapCheckListener = new ItemListener() {
                        public void itemStateChanged(ItemEvent e)
                        {
-                               _tileCacher.clearAll();
+                               _tileManager.clearMemoryCaches();
                                _recalculate = true;
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, e.getStateChange() == ItemEvent.SELECTED);
                                UpdateMessageBroker.informSubscribers(); // to let menu know
                                _recalculate = true;
                                Config.setConfigBoolean(Config.KEY_SHOW_MAP, e.getStateChange() == ItemEvent.SELECTED);
                                UpdateMessageBroker.informSubscribers(); // to let menu know
@@ -372,10 +373,10 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                _prevSelectedPoint = selectedPoint;
                        }
 
                                _prevSelectedPoint = selectedPoint;
                        }
 
-                       // Draw the mapImage if necessary
+                       // Draw the map contents if necessary
                        if ((_mapImage == null || _recalculate))
                        {
                        if ((_mapImage == null || _recalculate))
                        {
-                               getMapTiles();
+                               paintMapContents();
                                _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getCentreTileY());
                        }
                        // Draw the prepared image onto the panel
                                _scaleBar.updateScale(_mapPosition.getZoom(), _mapPosition.getCentreTileY());
                        }
                        // Draw the prepared image onto the panel
@@ -406,9 +407,9 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
 
 
        /**
 
 
        /**
-        * Get the map tiles for the current zoom level and given tile parameters
+        * Paint the map tiles and the points on to the _mapImage
         */
         */
-       private void getMapTiles()
+       private void paintMapContents()
        {
                if (_mapImage == null || _mapImage.getWidth() != getWidth() || _mapImage.getHeight() != getHeight())
                {
        {
                if (_mapImage == null || _mapImage.getWidth() != getWidth() || _mapImage.getHeight() != getHeight())
                {
@@ -427,16 +428,17 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
 
                // reset error message
                if (!showMap) {_shownOsmErrorAlready = false;}
 
                // reset error message
                if (!showMap) {_shownOsmErrorAlready = false;}
+               _recalculate = false;
                // Only get map tiles if selected
                if (showMap)
                {
                        // init tile cacher
                // Only get map tiles if selected
                if (showMap)
                {
                        // init tile cacher
-                       _tileCacher.centreMap(_mapPosition.getZoom(), _mapPosition.getCentreTileX(), _mapPosition.getCentreTileY());
+                       _tileManager.centreMap(_mapPosition.getZoom(), _mapPosition.getCentreTileX(), _mapPosition.getCentreTileY());
 
                        boolean loadingFailed = false;
                        if (_mapImage == null) return;
 
 
                        boolean loadingFailed = false;
                        if (_mapImage == null) return;
 
-                       if (_tileCacher.isOverzoomed())
+                       if (_tileManager.isOverzoomed())
                        {
                                // display overzoom message
                                g.setColor(COLOR_MESSAGES);
                        {
                                // display overzoom message
                                g.setColor(COLOR_MESSAGES);
@@ -444,6 +446,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        }
                        else
                        {
                        }
                        else
                        {
+                               int numLayers = _tileManager.getNumLayers();
                                // Loop over tiles drawing each one
                                int[] tileIndices = _mapPosition.getTileIndices(getWidth(), getHeight());
                                int[] pixelOffsets = _mapPosition.getDisplayOffsets(getWidth(), getHeight());
                                // Loop over tiles drawing each one
                                int[] tileIndices = _mapPosition.getTileIndices(getWidth(), getHeight());
                                int[] pixelOffsets = _mapPosition.getDisplayOffsets(getWidth(), getHeight());
@@ -453,9 +456,13 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                        for (int tileY = tileIndices[2]; tileY <= tileIndices[3]; tileY++)
                                        {
                                                int y = (tileY - tileIndices[2]) * 256 - pixelOffsets[1];
                                        for (int tileY = tileIndices[2]; tileY <= tileIndices[3]; tileY++)
                                        {
                                                int y = (tileY - tileIndices[2]) * 256 - pixelOffsets[1];
-                                               Image image = _tileCacher.getTile(tileX, tileY);
-                                               if (image != null) {
-                                                       g.drawImage(image, x, y, 256, 256, null);
+                                               // Loop over layers
+                                               for (int l=0; l<numLayers; l++)
+                                               {
+                                                       Image image = _tileManager.getTile(l, tileX, tileY);
+                                                       if (image != null) {
+                                                               g.drawImage(image, x, y, 256, 256, null);
+                                                       }
                                                }
                                        }
                                }
                                                }
                                        }
                                }
@@ -485,7 +492,6 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                // free g
                g.dispose();
 
                // free g
                g.dispose();
 
-               _recalculate = false;
                // Zoom to fit if no points found
                if (pointsPainted <= 0 && _checkBounds) {
                        zoomToFit();
                // Zoom to fit if no points found
                if (pointsPainted <= 0 && _checkBounds) {
                        zoomToFit();
@@ -919,7 +925,7 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        _checkBounds = true;
                }
                if ((inUpdateType & DataSubscriber.MAPSERVER_CHANGED) > 0) {
                        _checkBounds = true;
                }
                if ((inUpdateType & DataSubscriber.MAPSERVER_CHANGED) > 0) {
-                       _tileCacher.setTileConfig(new MapTileConfig());
+                       _tileManager.resetConfig();
                }
                repaint();
                // enable or disable components
                }
                repaint();
                // enable or disable components
@@ -938,8 +944,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
        {
                int code = inE.getKeyCode();
                int currPointIndex = _selection.getCurrentPointIndex();
        {
                int code = inE.getKeyCode();
                int currPointIndex = _selection.getCurrentPointIndex();
-               // Check for meta key
-               if (inE.isControlDown())
+               // Check for Ctrl key (for Linux/Win) or meta key (Clover key for Mac)
+               if (inE.isControlDown() || inE.isMetaDown())
                {
                        // Check for arrow keys to zoom in and out
                        if (code == KeyEvent.VK_UP)
                {
                        // Check for arrow keys to zoom in and out
                        if (code == KeyEvent.VK_UP)
@@ -951,6 +957,17 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                                _trackInfo.selectPoint(currPointIndex-1);
                        else if (code == KeyEvent.VK_RIGHT)
                                _trackInfo.selectPoint(currPointIndex+1);
                                _trackInfo.selectPoint(currPointIndex-1);
                        else if (code == KeyEvent.VK_RIGHT)
                                _trackInfo.selectPoint(currPointIndex+1);
+                       else if (code == KeyEvent.VK_PAGE_UP)
+                               _trackInfo.selectPoint(Checker.getPreviousSegmentStart(
+                                       _trackInfo.getTrack(), _trackInfo.getSelection().getCurrentPointIndex()));
+                       else if (code == KeyEvent.VK_PAGE_DOWN)
+                               _trackInfo.selectPoint(Checker.getNextSegmentStart(
+                                       _trackInfo.getTrack(), _trackInfo.getSelection().getCurrentPointIndex()));
+                       // Check for home and end
+                       else if (code == KeyEvent.VK_HOME)
+                               _trackInfo.selectPoint(0);
+                       else if (code == KeyEvent.VK_END)
+                               _trackInfo.selectPoint(_trackInfo.getTrack().getNumPoints()-1);
                }
                else
                {
                }
                else
                {
@@ -966,9 +983,8 @@ public class MapCanvas extends JPanel implements MouseListener, MouseMotionListe
                        else if (code == KeyEvent.VK_LEFT)
                                rightwardsPan = -PAN_DISTANCE;
                        panMap(rightwardsPan, upwardsPan);
                        else if (code == KeyEvent.VK_LEFT)
                                rightwardsPan = -PAN_DISTANCE;
                        panMap(rightwardsPan, upwardsPan);
-                       // Check for delete key to delete current point
-                       if (code == KeyEvent.VK_DELETE && currPointIndex >= 0)
-                       {
+                       // Check for backspace key to delete current point (delete key already handled by menu)
+                       if (code == KeyEvent.VK_BACK_SPACE && currPointIndex >= 0) {
                                _app.deleteCurrentPoint();
                        }
                }
                                _app.deleteCurrentPoint();
                        }
                }
diff --git a/tim/prune/gui/map/MapSource.java b/tim/prune/gui/map/MapSource.java
new file mode 100644 (file)
index 0000000..c2311ae
--- /dev/null
@@ -0,0 +1,124 @@
+package tim.prune.gui.map;
+
+import java.net.MalformedURLException;
+import java.net.URL;
+
+/**
+ * Class to represent any map source, whether an OsmMapSource
+ * or one of the more complicated ones.
+ * Map sources may contain just one or several layers, and may
+ * build their URLs in different ways depending on the source
+ */
+public abstract class MapSource
+{
+       /**
+        * @return the number of layers used in this source
+        */
+       public abstract int getNumLayers();
+
+       /**
+        * @return the name of the source
+        */
+       public abstract String getName();
+
+       /**
+        * @return the base url for the specified layer
+        */
+       public abstract String getBaseUrl(int inLayerNum);
+
+       /**
+        * @return the site name for the specified layer
+        */
+       public abstract String getSiteName(int inLayerNum);
+
+       /**
+        * @return the file extension for the specified layer
+        */
+       public abstract String getFileExtension(int inLayerNum);
+
+       /**
+        * Make the URL to get the specified tile
+        * @param inLayerNum number of layer, from 0 (base) to getNumLayers-1 (top)
+        * @param inZoom zoom level
+        * @param inX x coordinate of tile
+        * @param inY y coordinate of tile
+        * @return URL as string
+        */
+       public abstract String makeURL(int inLayerNum, int inZoom, int inX, int inY);
+
+       /**
+        * @return the maximum zoom level for this source
+        */
+       public abstract int getMaxZoomLevel();
+
+       /**
+        * Make a relative file path from the base directory including site name
+        * @param inLayerNum layer number
+        * @param inZoom zoom level
+        * @param inX x coordinate
+        * @param inY y coordinate
+        * @return relative file path as String
+        */
+       public String makeFilePath(int inLayerNum, int inZoom, int inX, int inY)
+       {
+               return getSiteName(inLayerNum) + inZoom + "/" + inX + "/" + inY + getFileExtension(inLayerNum);
+       }
+
+       /**
+        * Checks the given url for having the right prefix and trailing slash
+        * @param inUrl url to check
+        * @return validated url with correct prefix and trailing slash, or null
+        */
+       protected static String fixBaseUrl(String inUrl)
+       {
+               if (inUrl == null || inUrl.equals("")) {return null;}
+               String url = inUrl;
+               // check prefix
+               try {
+                       new URL(url);
+               }
+               catch (MalformedURLException e) {
+                       // add the http protocol
+                       url = "http://" + url;
+               }
+               // check trailing /
+               if (!url.endsWith("/")) {
+                       url = url + "/";
+               }
+               return url;
+       }
+
+       /**
+        * Fix the site name by stripping off protocol and www.
+        * This is used to create the file path for disk caching
+        * @param inUrl url to strip
+        * @return stripped url
+        */
+       protected static String fixSiteName(String inUrl)
+       {
+               if (inUrl == null || inUrl.equals("")) {return null;}
+               String url = inUrl.toLowerCase();
+               int idx = url.indexOf("://");
+               if (idx >= 0) {url = url.substring(idx + 3);}
+               if (url.startsWith("www.")) {url = url.substring(4);}
+               return url;
+       }
+
+       /**
+        * @return string which can be written to the Config
+        */
+       public abstract String getConfigString();
+
+       /**
+        * @return semicolon-separated list of base urls in order
+        */
+       public String getSiteStrings()
+       {
+               String s = "";
+               for (int i=0; i<getNumLayers(); i++) {
+                       String url = getBaseUrl(i);
+                       if (url != null) {s = s + url + ";";}
+               }
+               return s;
+       }
+}
diff --git a/tim/prune/gui/map/MapSourceLibrary.java b/tim/prune/gui/map/MapSourceLibrary.java
new file mode 100644 (file)
index 0000000..df30219
--- /dev/null
@@ -0,0 +1,141 @@
+package tim.prune.gui.map;
+
+import java.util.ArrayList;
+
+import tim.prune.config.Config;
+
+/**
+ * Class to hold a library for all the map sources
+ * and provide access to each one
+ */
+public abstract class MapSourceLibrary
+{
+       /** list of map sources */
+       private static ArrayList<MapSource> _sourceList = null;
+       /** Number of fixed sources */
+       private static int _numFixedSources = 0;
+
+       // Static block to initialise source list
+       static
+       {
+               _sourceList = new ArrayList<MapSource>();
+               addFixedSources();
+               _numFixedSources = _sourceList.size();
+               addConfigSources();
+       }
+
+       /** Private constructor to block instantiation */
+       private MapSourceLibrary() {}
+
+
+       /** @return number of fixed sources which shouldn't be deleted */
+       public static int getNumFixedSources() {
+               return _numFixedSources;
+       }
+
+       /**
+        * Initialise source list by adding bare minimum
+        */
+       private static void addFixedSources()
+       {
+               _sourceList.add(new OsmMapSource("Mapnik", "http://tile.openstreetmap.org/"));
+               _sourceList.add(new OsmMapSource("Osma", "http://tah.openstreetmap.org/Tiles/tile/"));
+               _sourceList.add(new OsmMapSource("Cyclemap", "http://andy.sandbox.cloudmade.com/tiles/cycle/"));
+               _sourceList.add(new OsmMapSource("Reitkarte", "http://topo.geofabrik.de/hills/",
+                       "http://topo.openstreetmap.de/topo/", 18));
+               _sourceList.add(new MffMapSource("Mapsforfree", "http://maps-for-free.com/layer/relief/", ".jpg",
+                       "http://maps-for-free.com/layer/water/", ".gif", 11));
+               _sourceList.add(new CloudmadeMapSource("Pale Dawn", "998", 18));
+       }
+
+       /**
+        * Add custom sources from Config to the library
+        */
+       private static void addConfigSources()
+       {
+               String configString = Config.getConfigString(Config.KEY_MAPSOURCE_LIST);
+               if (configString != null && configString.length() > 10)
+               {
+                       // Loop over sources in string, separated by vertical bars
+                       int splitPos = configString.indexOf('|');
+                       while (splitPos > 0)
+                       {
+                               String sourceString = configString.substring(0, splitPos);
+                               MapSource source = OsmMapSource.fromConfig(sourceString);
+                               if (source == null) {source = CloudmadeMapSource.fromConfig(sourceString);}
+                               if (source != null) {
+                                       _sourceList.add(source);
+                               }
+                               configString = configString.substring(splitPos+1);
+                               splitPos = configString.indexOf('|');
+                       }
+               }
+       }
+
+       /**
+        * @return current number of sources
+        */
+       public static int getNumSources() {
+               return _sourceList.size();
+       }
+
+       /**
+        * Add the given MapSource to the list (at the end)
+        * @param inSource MapSource object
+        */
+       public static void addSource(MapSource inSource) {
+               // Check whether source is already there?  Check whether valid?
+               _sourceList.add(inSource);
+       }
+
+       /**
+        * @param inIndex source index number
+        * @return corresponding map source object
+        */
+       public static MapSource getSource(int inIndex)
+       {
+               // Check whether within range
+               if (inIndex < 0 || inIndex >= _sourceList.size()) {return null;}
+               return _sourceList.get(inIndex);
+       }
+
+       /**
+        * Delete the specified source
+        * @param inIndex index of source to delete
+        */
+       public static void deleteSource(int inIndex)
+       {
+               if (inIndex >= _numFixedSources) {
+                       _sourceList.remove(inIndex);
+               }
+       }
+
+       /**
+        * Check whether the given name already exists in the library (case-insensitive)
+        * @param inName name to check
+        * @return true if already exists, false otherwise
+        */
+       public static boolean hasSourceName(String inName)
+       {
+               if (inName == null) {return false;}
+               String checkName = inName.toLowerCase().trim();
+               for (int i=0; i<getNumSources(); i++)
+               {
+                       String name = getSource(i).getName().toLowerCase();
+                       if (name.equals(checkName)) {return true;}
+               }
+               return false;
+       }
+
+       /**
+        * @return String containing all custom-added sources as a |-separated list
+        */
+       public static String getConfigString()
+       {
+               StringBuilder builder = new StringBuilder();
+               for (int i=getNumFixedSources(); i<getNumSources(); i++) {
+                       builder.append(getSource(i).getConfigString()).append('|');
+               }
+               return builder.toString();
+       }
+}
diff --git a/tim/prune/gui/map/MapTileCacher.java b/tim/prune/gui/map/MapTileCacher.java
deleted file mode 100644 (file)
index 366e1ad..0000000
+++ /dev/null
@@ -1,226 +0,0 @@
-package tim.prune.gui.map;
-
-import java.awt.Image;
-import java.awt.Toolkit;
-import java.awt.image.ImageObserver;
-import java.net.MalformedURLException;
-import java.net.URL;
-
-
-/**
- * Class to handle the caching of map tiles from openstreetmap
- */
-public class MapTileCacher implements ImageObserver
-{
-       /** Parent to be informed of updates */
-       private MapCanvas _parent = null;
-       /** Array of images to hold tiles */
-       private Image[] _tiles = new Image[GRID_SIZE * GRID_SIZE];
-       /** Current zoom level */
-       private int _zoom = -1;
-       /** X coordinate of central tile */
-       private int _tileX = -1;
-       /** Y coordinate of central tile */
-       private int _tileY = -1;
-       /** X coord of grid centre */
-       private int _gridCentreX = 0;
-       /** Y coord of grid centre */
-       private int _gridCentreY = 0;
-       /** Tile configuration */
-       private MapTileConfig _tileConfig = null;
-
-       /** Grid size */
-       private static final int GRID_SIZE = 15;
-       /** max zoom level of map tiles */
-       private static final int MAX_TILE_ZOOM = 18;
-
-
-       /**
-        * Constructor
-        * @param inParent parent canvas to be informed of updates
-        */
-       public MapTileCacher(MapCanvas inParent)
-       {
-               _parent = inParent;
-       }
-
-       /**
-        * Recentre the map and clear the cache
-        * @param inZoom zoom level
-        * @param inTileX x coord of central tile
-        * @param inTileY y coord of central tile
-        */
-       public void centreMap(int inZoom, int inTileX, int inTileY)
-       {
-               int shift = Math.max(Math.abs(inTileX-_tileX), Math.abs(inTileY - _tileY));
-               if (shift == 0) {return;}
-               // Clear cache if either zoom has changed or map has jumped too far
-               if (inZoom != _zoom || shift > GRID_SIZE/2)
-               {
-                       _zoom = inZoom;
-                       clearAll();
-               }
-               _gridCentreX = getCacheCoordinate(_gridCentreX + inTileX - _tileX);
-               _gridCentreY = getCacheCoordinate(_gridCentreY + inTileY - _tileY);
-               _tileX = inTileX;
-               _tileY = inTileY;
-               // Mark boundaries as invalid
-               for (int i=0; i<GRID_SIZE; i++)
-               {
-                       _tiles[getArrayIndex(_tileX + GRID_SIZE/2 + 1, _tileY + i - GRID_SIZE/2)] = null;
-                       _tiles[getArrayIndex(_tileX + i - GRID_SIZE/2, _tileY + GRID_SIZE/2 + 1)] = null;
-               }
-       }
-
-       /**
-        * Clear all the cached images
-        */
-       public void clearAll()
-       {
-               // Clear all images if zoom changed
-               for (int i=0; i<_tiles.length; i++) {
-                       _tiles[i] = null;
-               }
-       }
-
-       /**
-        * @param inX x index of tile
-        * @param inY y index of tile
-        * @return selected tile if already loaded, or null otherwise
-        */
-       public Image getTile(int inX, int inY)
-       {
-               if (_tileConfig == null) {_tileConfig = new MapTileConfig();}
-               int arrayIndex = getArrayIndex(inX, inY);
-               Image image = _tiles[arrayIndex];
-               if (image != null)
-               {
-                       // image already finished loading so return it
-                       return image;
-               }
-
-               // Protect against zoom > max
-               if (isOverzoomed()) return null;
-
-               // Trigger load if not already triggered
-               // Work out tile coords for URL
-               int urlX = getUrlCoordinate(inX, _zoom);
-               int urlY = getUrlCoordinate(inY, _zoom);
-               try
-               {
-                       // Use configured tile server
-                       String url = _tileConfig.getUrl() + _zoom + "/" + urlX + "/" + urlY + ".png";
-                       // Load image asynchronously, using observer
-                       image = Toolkit.getDefaultToolkit().createImage(new URL(url));
-                       _tiles[arrayIndex] = image;
-                       if (image.getWidth(this) > 0) {return image;}
-               }
-               catch (MalformedURLException urle) {} // ignore
-               return null;
-       }
-
-       /**
-        * @return true if zoom is too high for tiles
-        */
-       public boolean isOverzoomed()
-       {
-               return (_zoom > MAX_TILE_ZOOM);
-       }
-
-       /**
-        * Get the array index for the given coordinates
-        * @param inX x coord of tile
-        * @param inY y coord of tile
-        * @return array index
-        */
-       private int getArrayIndex(int inX, int inY)
-       {
-               //System.out.println("Getting array index for (" + inX + ", " + inY + ") where the centre is at ("  + _tileX + ", " + _tileY
-               //      + ") and grid coords (" + _gridCentreX + ", " + _gridCentreY + ")");
-               int x = getCacheCoordinate(inX - _tileX + _gridCentreX);
-               int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
-               //System.out.println("Transformed to (" + x + ", " + y + ")");
-               return (x + y * GRID_SIZE);
-       }
-
-       /**
-        * Transform a coordinate from map tiles to array coordinates
-        * @param inTile coordinate of tile
-        * @return coordinate in array (wrapping around cache grid)
-        */
-       private static int getCacheCoordinate(int inTile)
-       {
-               int tile = inTile;
-               while (tile >= GRID_SIZE) {tile -= GRID_SIZE;}
-               while (tile < 0) {tile += GRID_SIZE;}
-               return tile;
-       }
-
-       /**
-        * Make sure a url coordinate is within range
-        * @param inTile coordinate of tile in map system
-        * @param inZoom zoom factor
-        * @return coordinate for url (either vertical or horizontal)
-        */
-       private static int getUrlCoordinate(int inTile, int inZoom)
-       {
-               int mapSize = 1 << inZoom;
-               int coord = inTile;
-               while (coord >= mapSize) {coord -= mapSize;}
-               while (coord < 0) {coord += mapSize;}
-               // coord is now between 0 and mapsize
-               return coord;
-       }
-
-       /**
-        * Convert to string for debug
-        * @see java.lang.Object#toString()
-        */
-       public String toString()
-       {
-               StringBuffer result = new StringBuffer("Grid centre (" + _gridCentreX + "," + _gridCentreY + ") - (" + _tileX + "," + _tileY + ")\n");
-               for (int i=0; i<GRID_SIZE; i++)
-               {
-                       for (int j=0; j<GRID_SIZE; j++) {
-                               if (i == _gridCentreY && j == _gridCentreX) {
-                                       result.append(_tiles[j + i*GRID_SIZE] == null?"c":"C");
-                               }
-                               else {
-                                       result.append(_tiles[j + i*GRID_SIZE] == null?".":"*");
-                               }
-                       }
-                       result.append("\n");
-               }
-               return result.toString();
-       }
-
-       /**
-        * Method called by image loader to inform of updates to the tiles
-        * @param img the image
-        * @param infoflags flags describing how much of the image is known
-        * @param x ignored
-        * @param y ignored
-        * @param width ignored
-        * @param height ignored
-        * @return false to carry on loading, true to stop
-        */
-       public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
-       {
-               boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0;
-               boolean error = (infoflags & ImageObserver.ERROR) > 0;
-               if (loaded || error) {
-                       _parent.tilesUpdated(loaded);
-               }
-               return !loaded;
-       }
-
-       /**
-        * Set or reset the tile config
-        * @param inConfig object containing tile config
-        */
-       public void setTileConfig(MapTileConfig inConfig)
-       {
-               _tileConfig = inConfig;
-               clearAll();
-       }
-}
diff --git a/tim/prune/gui/map/MapTileConfig.java b/tim/prune/gui/map/MapTileConfig.java
deleted file mode 100644 (file)
index e545125..0000000
+++ /dev/null
@@ -1,92 +0,0 @@
-package tim.prune.gui.map;
-
-import java.net.MalformedURLException;
-import java.net.URL;
-
-import tim.prune.config.Config;
-
-/**
- * Class to hold the config for the map tiles
- * and retrieve the correct URL prefix
- */
-public class MapTileConfig
-{
-       /** Index of map server */
-       private int _index = 0;
-       /** Url for other */
-       private String _url = null;
-
-       /** server urls for known maps */
-       private static final String[] SERVER_URLS = {
-               "http://tile.openstreetmap.org/", // mapnik
-               "http://tah.openstreetmap.org/Tiles/tile/",      // osma
-               "http://andy.sandbox.cloudmade.com/tiles/cycle/" // cyclemap
-       };
-       /** Index of 'other' server with freeform url */
-       private static final int OTHER_SERVER_NUM = 3;
-
-
-       /**
-        * Default constructor using Config
-        */
-       public MapTileConfig()
-       {
-               _index = Config.getConfigInt(Config.KEY_MAPSERVERINDEX);
-               _url = fixUrl(Config.getConfigString(Config.KEY_MAPSERVERURL));
-               // reset index wrong or if other url too short
-               if (_index < 0 || _index > OTHER_SERVER_NUM ||
-                       (_index == OTHER_SERVER_NUM && (_url == null || _url.length() < 5)))
-               {
-                       _index = 0;
-               }
-       }
-
-       /**
-        * @return url
-        */
-       public String getUrl()
-       {
-               if (_index == OTHER_SERVER_NUM) {return _url;}
-               return SERVER_URLS[_index];
-       }
-
-       /**
-        * Checks the given url for having the right prefix and trailing slash
-        * @param inUrl url to check
-        * @return validated url with correct prefix and trailing slash, or null
-        */
-       private static String fixUrl(String inUrl)
-       {
-               if (inUrl == null || inUrl.equals("")) {return null;}
-               String url = inUrl;
-               // check prefix
-               try {
-                       new URL(url);
-               }
-               catch (MalformedURLException e) {
-                       // add the http protocol
-                       url = "http://" + url;
-               }
-               // check trailing /
-               if (!url.endsWith("/")) {
-                       url = url + "/";
-               }
-               return url;
-       }
-
-       /**
-        * @param inOther other config object
-        * @return true if the objects are exactly the same
-        */
-       public boolean equals(MapTileConfig inOther)
-       {
-               // Other object must be non-null and must have same index
-               if (inOther == null || inOther._index != _index) {return false;}
-               // Check url if other selected
-               if (_index == OTHER_SERVER_NUM) {
-                       return inOther._url.equals(_url);
-               }
-               // Not other so must match
-               return true;
-       }
-}
diff --git a/tim/prune/gui/map/MapTileManager.java b/tim/prune/gui/map/MapTileManager.java
new file mode 100644 (file)
index 0000000..9f1fbfe
--- /dev/null
@@ -0,0 +1,178 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+import java.awt.Toolkit;
+import java.awt.image.ImageObserver;
+import java.net.MalformedURLException;
+import java.net.URL;
+
+import tim.prune.config.Config;
+
+/**
+ * Class responsible for managing the map tiles,
+ * including invoking the correct memory cacher(s) and/or disk cacher(s)
+ */
+public class MapTileManager implements ImageObserver
+{
+       /** Parent object to inform when tiles received */
+       private MapCanvas _parent = null;
+       /** Current map source */
+       private MapSource _mapSource = null;
+       /** Array of tile caches, one per layer */
+       private MemTileCacher[] _tempCaches = null;
+       /** Number of layers */
+       private int _numLayers = -1;
+       /** Current zoom level */
+       private int _zoom = 0;
+
+
+       /**
+        * Constructor
+        * @param inParent parent canvas to be informed of updates
+        */
+       public MapTileManager(MapCanvas inParent)
+       {
+               _parent = inParent;
+               resetConfig();
+       }
+
+       /**
+        * Recentre the map
+        * @param inZoom zoom level
+        * @param inTileX x coord of central tile
+        * @param inTileY y coord of central tile
+        */
+       public void centreMap(int inZoom, int inTileX, int inTileY)
+       {
+               _zoom = inZoom;
+               // Pass params onto all memory cachers
+               if (_tempCaches != null) {
+                       for (int i=0; i<_tempCaches.length; i++) {
+                               _tempCaches[i].centreMap(inZoom, inTileX, inTileY);
+                       }
+               }
+       }
+
+       /**
+        * @return true if zoom is too high for tiles
+        */
+       public boolean isOverzoomed()
+       {
+               // Ask current map source what maximum zoom is
+               int maxZoom = (_mapSource == null?0:_mapSource.getMaxZoomLevel());
+               return (_zoom > maxZoom);
+       }
+
+       /**
+        * Clear all the memory caches due to changed config / zoom
+        */
+       public void clearMemoryCaches()
+       {
+               int numLayers = _mapSource.getNumLayers();
+               if (_tempCaches == null || _tempCaches.length != numLayers) {
+                       // Ccahers don't match, so need to create the right number of them
+                       _tempCaches = new MemTileCacher[numLayers];
+                       for (int i=0; i<numLayers; i++) {
+                               _tempCaches[i] = new MemTileCacher();
+                       }
+               }
+               else {
+                       // Cachers already there, just need to be cleared
+                       for (int i=0; i<numLayers; i++) {
+                               _tempCaches[i].clearAll();
+                       }
+               }
+       }
+
+       /**
+        * Reset the map source configuration, apparently it has changed
+        */
+       public void resetConfig()
+       {
+               int sourceNum = Config.getConfigInt(Config.KEY_MAPSOURCE_INDEX);
+               _mapSource = MapSourceLibrary.getSource(sourceNum);
+               if (_mapSource == null) {_mapSource = MapSourceLibrary.getSource(0);}
+               clearMemoryCaches();
+               _numLayers = _mapSource.getNumLayers();
+       }
+
+       /**
+        * @return the number of layers in the map
+        */
+       public int getNumLayers()
+       {
+               return _numLayers;
+       }
+
+       /**
+        * @param inLayer layer number, starting from 0
+        * @param inX x index of tile
+        * @param inY y index of tile
+        * @return selected tile if already loaded, or null otherwise
+        */
+       public Image getTile(int inLayer, int inX, int inY)
+       {
+               // Check first in memory cache for tile
+               MemTileCacher tempCache = _tempCaches[inLayer]; // Should probably guard against nulls and array indexes here
+               Image tile = tempCache.getTile(inX, inY);
+               if (tile != null) {
+                       return tile;
+               }
+
+               // Tile wasn't in memory, but maybe it's in disk cache (if there is one)
+               String diskCachePath = Config.getConfigString(Config.KEY_DISK_CACHE);
+               boolean useDisk = (diskCachePath != null);
+               boolean onlineMode = Config.getConfigBoolean(Config.KEY_ONLINE_MODE);
+               if (useDisk)
+               {
+                       tile = DiskTileCacher.getTile(diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), onlineMode);
+                       if (tile != null) {
+                               // Pass tile to memory cache
+                               tempCache.setTile(tile, inX, inY);
+                               if (tile.getWidth(this) > 0) {return tile;}
+                               return null;
+                       }
+               }
+               // Tile wasn't in memory or on disk, so if online let's get it
+               if (onlineMode)
+               {
+                       try
+                       {
+                               URL tileUrl = new URL(_mapSource.makeURL(inLayer, _zoom, inX, inY));
+                               if (useDisk) {
+                                       // Copy image directly from URL stream to disk cache
+                                       DiskTileCacher.saveTile(tileUrl, diskCachePath, _mapSource.makeFilePath(inLayer, _zoom, inX, inY), this);
+                               }
+                               else {
+                                       // Load image asynchronously, using observer
+                                       tile = Toolkit.getDefaultToolkit().createImage(tileUrl);
+                                       // Pass to memory cache
+                                       _tempCaches[inLayer].setTile(tile, inX, inY);
+                                       if (tile.getWidth(this) > 0) {return tile;}
+                               }
+                       }
+                       catch (MalformedURLException urle) {} // ignore
+               }
+               return null;
+       }
+
+       /**
+        * Method called by image loader to inform of updates to the tiles
+        * @param img the image
+        * @param infoflags flags describing how much of the image is known
+        * @param x ignored
+        * @param y ignored
+        * @param width ignored
+        * @param height ignored
+        * @return false to carry on loading, true to stop
+        */
+       public boolean imageUpdate(Image img, int infoflags, int x, int y, int width, int height)
+       {
+               boolean loaded = (infoflags & ImageObserver.ALLBITS) > 0;
+               boolean error = (infoflags & ImageObserver.ERROR) > 0;
+               if (loaded || error) {
+                       _parent.tilesUpdated(loaded);
+               }
+               return !loaded;
+       }
+}
diff --git a/tim/prune/gui/map/MemTileCacher.java b/tim/prune/gui/map/MemTileCacher.java
new file mode 100644 (file)
index 0000000..69b5f83
--- /dev/null
@@ -0,0 +1,115 @@
+package tim.prune.gui.map;
+
+import java.awt.Image;
+
+/**
+ * Class to act as a memory-based map tile cache
+ * For caching of tiles on disk, see the DiskTileCacher class.
+ */
+public class MemTileCacher
+{
+       /** Array of images to hold tiles */
+       private Image[] _tiles = new Image[GRID_SIZE * GRID_SIZE];
+       /** Current zoom level */
+       private int _zoom = -1;
+       /** X coordinate of central tile */
+       private int _tileX = -1;
+       /** Y coordinate of central tile */
+       private int _tileY = -1;
+       /** X coord of grid centre */
+       private int _gridCentreX = 0;
+       /** Y coord of grid centre */
+       private int _gridCentreY = 0;
+
+       /** Grid size */
+       private static final int GRID_SIZE = 15;
+
+       /**
+        * Recentre the map and clear the cache
+        * @param inZoom zoom level
+        * @param inTileX x coord of central tile
+        * @param inTileY y coord of central tile
+        */
+       public void centreMap(int inZoom, int inTileX, int inTileY)
+       {
+               int shift = Math.max(Math.abs(inTileX-_tileX), Math.abs(inTileY - _tileY));
+               if (shift == 0) {return;}
+               // Clear cache if either zoom has changed or map has jumped too far
+               if (inZoom != _zoom || shift > GRID_SIZE/2)
+               {
+                       _zoom = inZoom;
+                       clearAll();
+               }
+               _gridCentreX = getCacheCoordinate(_gridCentreX + inTileX - _tileX);
+               _gridCentreY = getCacheCoordinate(_gridCentreY + inTileY - _tileY);
+               _tileX = inTileX;
+               _tileY = inTileY;
+               // Mark boundaries as invalid
+               for (int i=0; i<GRID_SIZE; i++)
+               {
+                       _tiles[getArrayIndex(_tileX + GRID_SIZE/2 + 1, _tileY + i - GRID_SIZE/2)] = null;
+                       _tiles[getArrayIndex(_tileX + i - GRID_SIZE/2, _tileY + GRID_SIZE/2 + 1)] = null;
+               }
+       }
+
+       /**
+        * Transform a coordinate from map tiles to array coordinates
+        * @param inTile coordinate of tile
+        * @return coordinate in array (wrapping around cache grid)
+        */
+       private static int getCacheCoordinate(int inTile)
+       {
+               int tile = inTile;
+               while (tile >= GRID_SIZE) {tile -= GRID_SIZE;}
+               while (tile < 0) {tile += GRID_SIZE;}
+               return tile;
+       }
+
+       /**
+        * Get the array index for the given coordinates
+        * @param inX x coord of tile
+        * @param inY y coord of tile
+        * @return array index
+        */
+       private int getArrayIndex(int inX, int inY)
+       {
+               //System.out.println("Getting array index for (" + inX + ", " + inY + ") where the centre is at ("  + _tileX + ", " + _tileY
+               //      + ") and grid coords (" + _gridCentreX + ", " + _gridCentreY + ")");
+               int x = getCacheCoordinate(inX - _tileX + _gridCentreX);
+               int y = getCacheCoordinate(inY - _tileY + _gridCentreY);
+               //System.out.println("Transformed to (" + x + ", " + y + ")");
+               return (x + y * GRID_SIZE);
+       }
+
+       /**
+        * Clear all the cached images
+        */
+       public void clearAll()
+       {
+               // Clear all images if zoom changed
+               for (int i=0; i<_tiles.length; i++) {
+                       _tiles[i] = null;
+               }
+       }
+
+       /**
+        * @param inX x index of tile
+        * @param inY y index of tile
+        * @return selected tile if already loaded, or null otherwise
+        */
+       public Image getTile(int inX, int inY)
+       {
+               return _tiles[getArrayIndex(inX, inY)];
+       }
+
+       /**
+        * Save the specified tile at the given coordinates
+        * @param inTile image to save
+        * @param inX x coordinate of tile
+        * @param inY y coordinate of tile
+        */
+       public void setTile(Image inTile, int inX, int inY)
+       {
+               _tiles[getArrayIndex(inX, inY)] = inTile;
+       }
+}
diff --git a/tim/prune/gui/map/MffMapSource.java b/tim/prune/gui/map/MffMapSource.java
new file mode 100644 (file)
index 0000000..772d8e9
--- /dev/null
@@ -0,0 +1,96 @@
+package tim.prune.gui.map;
+
+import tim.prune.I18nManager;
+
+/**
+ * Class to provide a map source for maps-for-free sources
+ * These are double-layer sources with jpg and gif tiles
+ */
+public class MffMapSource extends MapSource
+{
+       /** Name for this source */
+       private String _name = null;
+       /** Base urls */
+       private String[] _baseUrls = null;
+       /** Site names */
+       private String[] _siteNames = null;
+       /** File extensions */
+       private String[] _extensions = null;
+       /** Maximum zoom level */
+       private int _maxZoom = 0;
+
+       /**
+        * Constructor giving name, url and maximum zoom
+        * @param inName source name
+        * @param inUrl base url
+        * @param inMaxZoom maximum zoom level
+        */
+       public MffMapSource(String inName, String inUrl1, String inExt1,
+               String inUrl2, String inExt2, int inMaxZoom)
+       {
+               _name = inName;
+               if (_name == null || _name.trim().equals("")) {_name = I18nManager.getText("mapsource.unknown");}
+               _baseUrls = new String[2];
+               _baseUrls[0] = fixBaseUrl(inUrl1);
+               _baseUrls[1] = fixBaseUrl(inUrl2);
+               _siteNames = new String[2];
+               _siteNames[0] = fixSiteName(_baseUrls[0]);
+               _siteNames[1] = fixSiteName(_baseUrls[1]);
+               _extensions = new String[2];
+               _extensions[0] = inExt1;
+               _extensions[1] = inExt2;
+               _maxZoom = inMaxZoom;
+       }
+
+       /**
+        * @return name
+        */
+       public String getName() {
+               return _name;
+       }
+
+       /** Number of layers is always 2 for mff sources */
+       public int getNumLayers() {
+               return 2;
+       }
+
+       /** Get base url for specified layer */
+       public String getBaseUrl(int inLayerNum) {
+               return _baseUrls[inLayerNum];
+       }
+
+       /** site name without protocol or www. */
+       public String getSiteName(int inLayerNum) {
+               return _siteNames[inLayerNum];
+       }
+
+       /**
+        * Make the URL to get the specified tile
+        */
+       public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
+       {
+               return _baseUrls[inLayerNum] + "z" + inZoom + "/row" + inY + "/" + inZoom + "_" + inX + "-" + inY + getFileExtension(inLayerNum);
+       }
+
+       /** Get right file extension for this layer */
+       public final String getFileExtension(int inLayerNum) {
+               return _extensions[inLayerNum];
+       }
+
+       /**
+        * @return maximum zoom level
+        */
+       public final int getMaxZoomLevel()
+       {
+               return _maxZoom;
+       }
+
+       /**
+        * @return semicolon-separated list of all fields
+        */
+       public String getConfigString()
+       {
+               // TODO: Maybe a gui will be necessary for this one day
+               return "not required";
+       }
+}
diff --git a/tim/prune/gui/map/OsmMapSource.java b/tim/prune/gui/map/OsmMapSource.java
new file mode 100644 (file)
index 0000000..7686307
--- /dev/null
@@ -0,0 +1,132 @@
+package tim.prune.gui.map;
+
+import tim.prune.I18nManager;
+
+/**
+ * Class to provide a map source for all OSM-like sources
+ * (eg mapnik, opencyclemap, openpistemap etc).
+ * These can be single-layer or double-layer sources with png tiles
+ */
+public class OsmMapSource extends MapSource
+{
+       /** Name for this source */
+       private String _name = null;
+       /** Base urls */
+       private String[] _baseUrls = null;
+       /** Site names */
+       private String[] _siteNames = null;
+       /** Maximum zoom level */
+       private int _maxZoom = 0;
+
+       /**
+        * Constructor giving single name and url
+        * @param inName source name
+        * @param inUrl base url
+        */
+       public OsmMapSource(String inName, String inUrl)
+       {
+               this(inName, inUrl, null, 18);
+       }
+
+       /**
+        * Constructor giving name, urls and maximum zoom
+        * @param inName source name
+        * @param inUrl1 base layer url
+        * @param inUrl2 upper layer url
+        * @param inMaxZoom maximum zoom level
+        */
+       public OsmMapSource(String inName, String inUrl1, String inUrl2, int inMaxZoom)
+       {
+               _name = inName;
+               if (_name == null || _name.trim().equals("")) {_name = I18nManager.getText("mapsource.unknown");}
+               _baseUrls = new String[2];
+               _baseUrls[0] = fixBaseUrl(inUrl1);
+               _baseUrls[1] = fixBaseUrl(inUrl2);
+               _siteNames = new String[2];
+               _siteNames[0] = fixSiteName(_baseUrls[0]);
+               _siteNames[1] = fixSiteName(_baseUrls[1]);
+               // Swap layers if second layer given without first
+               if (_baseUrls[0] == null && _baseUrls[1] != null)
+               {
+                       _baseUrls[0] = _baseUrls[1];
+                       _siteNames[0] = _siteNames[1];
+                       _baseUrls[1] = _siteNames[1] = null;
+               }
+               _maxZoom = inMaxZoom;
+       }
+
+       /**
+        * Construct a new map source from its config string
+        * @param inConfigString string from Config, separated by semicolons
+        * @return new map source, or null if not parseable
+        */
+       public static OsmMapSource fromConfig(String inConfigString)
+       {
+               OsmMapSource source = null;
+               if (inConfigString.startsWith("o:"))
+               {
+                       String[] items = inConfigString.substring(2).split(";");
+                       try {
+                               if (items.length == 3) {
+                                       source = new OsmMapSource(items[0], items[1], null, Integer.parseInt(items[2]));
+                               }
+                               else if (items.length == 4) {
+                                       source = new OsmMapSource(items[0], items[1], items[2], Integer.parseInt(items[3]));
+                               }
+                       } catch (NumberFormatException nfe) {}
+               }
+               return source;
+       }
+
+       /**
+        * @return name
+        */
+       public String getName() {
+               return _name;
+       }
+
+       /** Number of layers */
+       public int getNumLayers() {
+               return _baseUrls[1] == null?1:2;
+       }
+
+       /** Base url for this source */
+       public String getBaseUrl(int inLayerNum) {
+               return _baseUrls[inLayerNum];
+       }
+
+       /** site name without protocol or www. */
+       public String getSiteName(int inLayerNum) {
+               return _siteNames[inLayerNum];
+       }
+
+       /**
+        * Make the URL to get the specified tile
+        */
+       public String makeURL(int inLayerNum, int inZoom, int inX, int inY)
+       {
+               return _baseUrls[inLayerNum] + inZoom + "/" + inX + "/" + inY + getFileExtension(inLayerNum);
+       }
+
+       /** file extension is always png */
+       public final String getFileExtension(int inLayerNum) {
+               return ".png";
+       }
+
+       /**
+        * @return maximum zoom level
+        */
+       public final int getMaxZoomLevel()
+       {
+               return _maxZoom;
+       }
+
+
+       /**
+        * @return semicolon-separated list of all fields
+        */
+       public String getConfigString()
+       {
+               return "o:" +  getName() + ";" + getSiteStrings() + getMaxZoomLevel();
+       }
+}
diff --git a/tim/prune/gui/profile/AltitudeData.java b/tim/prune/gui/profile/AltitudeData.java
new file mode 100644 (file)
index 0000000..90130cc
--- /dev/null
@@ -0,0 +1,74 @@
+package tim.prune.gui.profile;
+
+import tim.prune.I18nManager;
+import tim.prune.data.Altitude;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Track;
+
+/**
+ * Class to provide a source of altitude data for the profile chart
+ */
+public class AltitudeData extends ProfileData
+{
+       /** Altitude format for values */
+       private Altitude.Format _altitudeFormat = Altitude.Format.NO_FORMAT;
+
+
+       /**
+        * Constructor
+        * @param inTrack track object
+        */
+       public AltitudeData(Track inTrack) {
+               super(inTrack);
+       }
+
+       /**
+        * Get the data and populate the instance arrays
+        */
+       public void init()
+       {
+               initArrays();
+               _hasData = false;
+               _altitudeFormat = Altitude.Format.NO_FORMAT;
+               if (_track != null) {
+                       for (int i=0; i<_track.getNumPoints(); i++)
+                       {
+                               DataPoint point = _track.getPoint(i);
+                               if (point != null && point.hasAltitude())
+                               {
+                                       // Point has an altitude - if it's the first one, use its format
+                                       if (_altitudeFormat == Altitude.Format.NO_FORMAT)
+                                       {
+                                               _altitudeFormat = point.getAltitude().getFormat();
+                                               _minValue = _maxValue = point.getAltitude().getValue();
+                                       }
+                                       // Store the value and maintain max and min values
+                                       double value = point.getAltitude().getValue(_altitudeFormat);
+                                       _pointValues[i] = value;
+                                       if (value < _minValue) {_minValue = value;}
+                                       if (value > _maxValue) {_maxValue = value;}
+
+                                       _hasData = true;
+                                       _pointHasData[i] = true;
+                               }
+                       }
+               }
+       }
+
+       /**
+        * @return text description including units
+        */
+       public String getLabel()
+       {
+               return I18nManager.getText("fieldname.altitude") + " ("
+                       + I18nManager.getText(_altitudeFormat==Altitude.Format.FEET?"units.feet.short":"units.metres.short")
+                       + ")";
+       }
+
+       /**
+        * @return key for message when no altitudes present
+        */
+       public String getNoDataKey() {
+               return "display.noaltitudes";
+       }
+}
diff --git a/tim/prune/gui/profile/ProfileChart.java b/tim/prune/gui/profile/ProfileChart.java
new file mode 100644 (file)
index 0000000..d989ebf
--- /dev/null
@@ -0,0 +1,351 @@
+package tim.prune.gui.profile;
+
+import java.awt.Color;
+import java.awt.Dimension;
+import java.awt.FlowLayout;
+import java.awt.Graphics;
+import java.awt.event.ActionEvent;
+import java.awt.event.ActionListener;
+import java.awt.event.MouseEvent;
+import java.awt.event.MouseListener;
+import javax.swing.JLabel;
+import javax.swing.JMenuItem;
+import javax.swing.JPopupMenu;
+
+import tim.prune.I18nManager;
+import tim.prune.config.ColourScheme;
+import tim.prune.config.Config;
+import tim.prune.data.TrackInfo;
+import tim.prune.gui.GenericDisplay;
+
+/**
+ * Chart component for the profile display
+ */
+public class ProfileChart extends GenericDisplay implements MouseListener
+{
+       /** Current scale factor in x direction*/
+       private double _xScaleFactor = 0.0;
+       /** Data to show on chart */
+       private ProfileData _data = null;
+       /** Label for chart type, units */
+       private JLabel _label = null;
+       /** Right-click popup menu */
+       private JPopupMenu _popup = null;
+
+       /** Possible scales to use */
+       private static final int[] LINE_SCALES = {10000, 5000, 2000, 1000, 500, 200, 100, 50, 10, 5};
+       /** Border width around black line */
+       private static final int BORDER_WIDTH = 6;
+       /** Minimum size for profile chart in pixels */
+       private static final Dimension MINIMUM_SIZE = new Dimension(200, 110);
+       /** Colour to use for text if no data found */
+       private static final Color COLOR_NODATA_TEXT = Color.GRAY;
+       /** Chart type */
+       private static enum ChartType {ALTITUDE, SPEED};
+
+
+       /**
+        * Constructor
+        * @param inTrackInfo Track info object
+        */
+       public ProfileChart(TrackInfo inTrackInfo)
+       {
+               super(inTrackInfo);
+               _data = new AltitudeData(inTrackInfo.getTrack());
+               addMouseListener(this);
+               setLayout(new FlowLayout(FlowLayout.LEFT));
+               _label = new JLabel("Altitude");
+               add(_label);
+               makePopup();
+       }
+
+
+       /**
+        * Override minimum size method to restrict slider
+        */
+       public Dimension getMinimumSize()
+       {
+               return MINIMUM_SIZE;
+       }
+
+       /**
+        * Override paint method to draw map
+        * @param g Graphics object
+        */
+       public void paint(Graphics g)
+       {
+               super.paint(g);
+               ColourScheme colourScheme = Config.getColourScheme();
+               paintBackground(g, colourScheme);
+               if (_track != null && _track.getNumPoints() > 0)
+               {
+                       _data.init();
+                       _label.setText(_data.getLabel());
+                       int width = getWidth();
+                       int height = getHeight();
+
+                       // Set up colours
+                       final Color barColour = colourScheme.getColour(ColourScheme.IDX_POINT);
+                       final Color rangeColour = colourScheme.getColour(ColourScheme.IDX_SELECTION);
+                       final Color currentColour = colourScheme.getColour(ColourScheme.IDX_PRIMARY);
+                       final Color secondColour = colourScheme.getColour(ColourScheme.IDX_SECONDARY);
+                       final Color lineColour = colourScheme.getColour(ColourScheme.IDX_LINES);
+
+                       // message if no data for the current field in track
+                       if (!_data.hasData())
+                       {
+                               g.setColor(lineColour);
+                               g.drawString(I18nManager.getText(_data.getNoDataKey()), 50, (height+_label.getHeight())/2);
+                               paintChildren(g);
+                               return;
+                       }
+
+                       // Find minimum and maximum values to plot
+                       double minValue = _data.getMinValue();
+                       double maxValue = _data.getMaxValue();
+                       if (maxValue <= minValue) {maxValue = minValue + 1;}
+
+                       final int numPoints = _track.getNumPoints();
+                       _xScaleFactor = 1.0 * (width - 2 * BORDER_WIDTH - 1) / numPoints;
+                       int usableHeight = height - 2 * BORDER_WIDTH - _label.getHeight();
+                       double yScaleFactor = 1.0 * usableHeight / (maxValue - minValue);
+                       int barWidth = (int) (_xScaleFactor + 1.0);
+                       int selectedPoint = _trackInfo.getSelection().getCurrentPointIndex();
+                       // selection start, end
+                       int selectionStart = -1, selectionEnd = -1;
+                       if (_trackInfo.getSelection().hasRangeSelected()) {
+                               selectionStart = _trackInfo.getSelection().getStart();
+                               selectionEnd = _trackInfo.getSelection().getEnd();
+                       }
+
+                       // horizontal lines for scale - set to round numbers eg 500
+                       int lineScale = getLineScale(minValue, maxValue);
+                       int scaleValue = (int) (minValue/lineScale + 1) * lineScale;
+                       int x = 0, y = 0;
+                       double value = 0.0;
+                       if (lineScale > 1)
+                       {
+                               g.setColor(lineColour);
+                               while (scaleValue < maxValue)
+                               {
+                                       y = height - BORDER_WIDTH - (int) (yScaleFactor * (scaleValue - minValue));
+                                       g.drawLine(BORDER_WIDTH + 1, y, width - BORDER_WIDTH - 1, y);
+                                       scaleValue += lineScale;
+                               }
+                       }
+
+                       try
+                       {
+                               // loop through points
+                               g.setColor(barColour);
+                               for (int p = 0; p < numPoints; p++)
+                               {
+                                       x = (int) (_xScaleFactor * p) + 1;
+                                       if (p == selectionStart)
+                                               g.setColor(rangeColour);
+                                       else if (p == (selectionEnd+1))
+                                               g.setColor(barColour);
+                                       if (_data.hasData(p))
+                                       {
+                                               value = _data.getData(p);
+                                               y = (int) (yScaleFactor * (value - minValue));
+                                               g.fillRect(BORDER_WIDTH+x, height-BORDER_WIDTH - y, barWidth, y);
+                                       }
+                               }
+                               // current point (make sure it's drawn last)
+                               if (_data.hasData(selectedPoint))
+                               {
+                                       x = (int) (_xScaleFactor * selectedPoint) + 1;
+                                       g.setColor(secondColour);
+                                       g.fillRect(BORDER_WIDTH + x, height-usableHeight-BORDER_WIDTH+1, barWidth, usableHeight-2);
+                                       g.setColor(currentColour);
+                                       value = _data.getData(selectedPoint);
+                                       y = (int) (yScaleFactor * (value - minValue));
+                                       g.fillRect(BORDER_WIDTH + x, height-BORDER_WIDTH - y, barWidth, y);
+                               }
+                       }
+                       catch (NullPointerException npe) { // ignore, probably due to data being changed
+                       }
+                       // Draw numbers on top of the graph to mark scale
+                       if (lineScale > 1)
+                       {
+                               int textHeight = g.getFontMetrics().getHeight();
+                               scaleValue = (int) (minValue / lineScale + 1) * lineScale;
+                               y = 0;
+                               g.setColor(currentColour);
+                               while (scaleValue < maxValue)
+                               {
+                                       y = height - BORDER_WIDTH - (int) (yScaleFactor * (scaleValue - minValue));
+                                       // Limit y so String isn't above border
+                                       if (y < (BORDER_WIDTH + textHeight)) {
+                                               y = BORDER_WIDTH + textHeight;
+                                       }
+                                       g.drawString(""+scaleValue, BORDER_WIDTH + 5, y);
+                                       scaleValue += lineScale;
+                               }
+                       }
+                       // Paint label on top
+                       paintChildren(g);
+               }
+       }
+
+
+       /**
+        * Paint the background for the chart
+        * @param inG graphics object
+        * @param inColourScheme colour scheme
+        */
+       private void paintBackground(Graphics inG, ColourScheme inColourScheme)
+       {
+               final int width = getWidth();
+               final int height = getHeight();
+               // Get colours
+               final Color borderColour = inColourScheme.getColour(ColourScheme.IDX_BORDERS);
+               final Color backgroundColour = inColourScheme.getColour(ColourScheme.IDX_BACKGROUND);
+               // background
+               inG.setColor(backgroundColour);
+               inG.fillRect(0, 0, width, height);
+               if (width < 2*BORDER_WIDTH || height < 2*BORDER_WIDTH) return;
+               // Display message if no data to be displayed
+               if (_track == null || _track.getNumPoints() <= 0)
+               {
+                       inG.setColor(COLOR_NODATA_TEXT);
+                       inG.drawString(I18nManager.getText("display.nodata"), 50, height/2);
+               }
+               else {
+                       inG.setColor(borderColour);
+                       inG.drawRect(BORDER_WIDTH, BORDER_WIDTH + _label.getHeight(),
+                               width - 2*BORDER_WIDTH, height-2*BORDER_WIDTH-_label.getHeight());
+               }
+       }
+
+       /**
+        * Make the popup menu for right-clicking the chart
+        */
+       private void makePopup()
+       {
+               _popup = new JPopupMenu();
+               JMenuItem altItem = new JMenuItem(I18nManager.getText("fieldname.altitude"));
+               altItem.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               changeView(ChartType.ALTITUDE);
+                       }});
+               _popup.add(altItem);
+               JMenuItem speedItem = new JMenuItem(I18nManager.getText("fieldname.speed"));
+               speedItem.addActionListener(new ActionListener() {
+                       public void actionPerformed(ActionEvent e)
+                       {
+                               changeView(ChartType.SPEED);
+                       }});
+               _popup.add(speedItem);
+       }
+
+       /**
+        * Work out the scale for the horizontal lines
+        * @param inMin min value of data
+        * @param inMax max value of data
+        * @return scale separation, or -1 for no scale
+        */
+       private int getLineScale(double inMin, double inMax)
+       {
+               if ((inMax - inMin) < 5 || inMax < 0) {
+                       return -1;
+               }
+               int numScales = LINE_SCALES.length;
+               for (int i=0; i<numScales; i++)
+               {
+                       int scale = LINE_SCALES[i];
+                       int numLines = (int)(inMax / scale) - (int)(inMin / scale);
+                       // Check for too many lines
+                       if (numLines > 10) return -1;
+                       // If more than 1 line then use this scale
+                       if (numLines > 1) return scale;
+               }
+               // no suitable scale found so just use minimum
+               return LINE_SCALES[numScales-1];
+       }
+
+
+       /**
+        * Method to inform map that data has changed
+        */
+       public void dataUpdated(byte inUpdateType)
+       {
+               _data.init();
+               repaint();
+       }
+
+       /**
+        * React to click on profile display
+        */
+       public void mouseClicked(MouseEvent e)
+       {
+               if (_track == null || _track.getNumPoints() < 1) {return;}
+               // left clicks
+               if (!e.isMetaDown())
+               {
+                       int xClick = e.getX();
+                       int yClick = e.getY();
+                       // Check click is within main area (not in border)
+                       if (xClick > BORDER_WIDTH && yClick > BORDER_WIDTH && xClick < (getWidth() - BORDER_WIDTH)
+                               && yClick < (getHeight() - BORDER_WIDTH))
+                       {
+                               // work out which data point is nearest and select it
+                               int pointNum = (int) ((e.getX() - BORDER_WIDTH) / _xScaleFactor);
+                               // If shift clicked, then extend selection
+                               if (e.isShiftDown()) {
+                                       _trackInfo.extendSelection(pointNum);
+                               }
+                               else {
+                                       _trackInfo.selectPoint(pointNum);
+                               }
+                       }
+               }
+               else {
+                       // right clicks
+                       _popup.show(this, e.getX(), e.getY());
+               }
+       }
+
+       /**
+        * Called by clicking on popup menu to change the view
+        * @param inType selected chart type
+        */
+       private void changeView(ChartType inType)
+       {
+               if (inType == ChartType.ALTITUDE && !(_data instanceof AltitudeData))
+               {
+                       _data = new AltitudeData(_track);
+               }
+               else if (inType == ChartType.SPEED && !(_data instanceof SpeedData)) {
+                       _data = new SpeedData(_track);
+               }
+               _data.init();
+               repaint();
+       }
+
+       /**
+        * mouse enter events ignored
+        */
+       public void mouseEntered(MouseEvent e)
+       {}
+
+       /**
+        * mouse exit events ignored
+        */
+       public void mouseExited(MouseEvent e)
+       {}
+
+       /**
+        * ignore mouse pressed for now too
+        */
+       public void mousePressed(MouseEvent e)
+       {}
+
+       /**
+        * and also ignore mouse released
+        */
+       public void mouseReleased(MouseEvent e)
+       {}
+}
diff --git a/tim/prune/gui/profile/ProfileData.java b/tim/prune/gui/profile/ProfileData.java
new file mode 100644 (file)
index 0000000..8b036a9
--- /dev/null
@@ -0,0 +1,101 @@
+package tim.prune.gui.profile;
+
+import tim.prune.data.Track;
+
+/**
+ * Abstract class for all sources of profile data,
+ * including altitudes and speeds
+ */
+public abstract class ProfileData
+{
+       /** Track object */
+       protected final Track _track;
+       /** Flag for availability of any data */
+       protected boolean _hasData = false;
+       /** Array of booleans for data per point */
+       protected boolean[] _pointHasData = null;
+       /** Array of values per point */
+       protected double[] _pointValues = null;
+       /** Minimum value for track */
+       protected double _minValue = 0.0;
+       /** Maximum value for track */
+       protected double _maxValue = 0.0;
+
+       /**
+        * Constructor giving track object
+        * @param inTrack track object
+        */
+       public ProfileData(Track inTrack)
+       {
+               _track = inTrack;
+       }
+
+       /**
+        * @return true if this source has any data at all
+        */
+       public boolean hasData() {
+               return _hasData;
+       }
+
+       /**
+        * @param inPointNum index of point
+        * @return true if that point has data
+        */
+       public boolean hasData(int inPointNum)
+       {
+               return (_hasData && _pointHasData != null && inPointNum >= 0
+                       && inPointNum < _pointHasData.length && _pointHasData[inPointNum]);
+       }
+
+       /**
+        * @param inPointNum index of point
+        * @return value corresponding to that point
+        */
+       public double getData(int inPointNum)
+       {
+               if (!hasData(inPointNum)) {return 0.0;}
+               return _pointValues[inPointNum];
+       }
+
+       /**
+        * @return minimum value
+        */
+       public double getMinValue() {
+               return _minValue;
+       }
+
+       /**
+        * @return maximum value
+        */
+       public double getMaxValue() {
+               return _maxValue;
+       }
+
+       /**
+        * Get the data from the track and populate the value arrays
+        */
+       public abstract void init();
+
+       /**
+        * @return text for label including units
+        */
+       public abstract String getLabel();
+
+       /**
+        * @return key for message when no data available
+        */
+       public abstract String getNoDataKey();
+
+       /**
+        * Initialise the data arrays
+        */
+       protected void initArrays()
+       {
+               int numTrackPoints = _track.getNumPoints();
+               if (_pointHasData == null || _pointHasData.length != numTrackPoints)
+               {
+                       _pointHasData = new boolean[numTrackPoints];
+                       _pointValues = new double[numTrackPoints];
+               }
+       }
+}
diff --git a/tim/prune/gui/profile/SpeedData.java b/tim/prune/gui/profile/SpeedData.java
new file mode 100644 (file)
index 0000000..d836543
--- /dev/null
@@ -0,0 +1,83 @@
+package tim.prune.gui.profile;
+
+import tim.prune.I18nManager;
+import tim.prune.config.Config;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Distance;
+import tim.prune.data.Track;
+import tim.prune.data.Distance.Units;
+
+/**
+ * Class to provide a source of speed data for the profile chart
+ */
+public class SpeedData extends ProfileData
+{
+       /** Flag for metric units */
+       private boolean _metric = true;
+
+       /**
+        * Constructor
+        * @param inTrack track object
+        */
+       public SpeedData(Track inTrack) {
+               super(inTrack);
+       }
+
+       /**
+        * Get the data and populate the instance arrays
+        */
+       public void init()
+       {
+               initArrays();
+               _metric = Config.getConfigBoolean(Config.KEY_METRIC_UNITS);
+               _hasData = false;
+               _minValue = _maxValue = 0.0;
+               if (_track != null) {
+                       DataPoint prevPrevPoint = null, prevPoint = null, point = null;
+                       for (int i=0; i<_track.getNumPoints(); i++)
+                       {
+                               point = _track.getPoint(i);
+                               if (prevPrevPoint != null && prevPrevPoint.hasTimestamp()
+                                       && prevPoint != null && prevPoint.hasTimestamp()
+                                       && point != null && point.hasTimestamp())
+                               {
+                                       // All three points have timestamps
+                                       double seconds = point.getTimestamp().getSecondsSince(prevPrevPoint.getTimestamp());
+                                       if (seconds > 0)
+                                       {
+                                               double distInRads = DataPoint.calculateRadiansBetween(prevPrevPoint, prevPoint)
+                                                       + DataPoint.calculateRadiansBetween(prevPoint, point);
+                                               double dist = Distance.convertRadiansToDistance(distInRads, _metric?Units.KILOMETRES:Units.MILES);
+                                               // Store the value and maintain max and min values
+                                               double value = dist / seconds * 60.0 * 60.0;
+                                               _pointValues[i-1] = value;
+                                               if (value < _minValue || _minValue == 0.0) {_minValue = value;}
+                                               if (value > _maxValue) {_maxValue = value;}
+
+                                               _hasData = true;
+                                               _pointHasData[i-1] = true;
+                                       }
+                               }
+                               // Exchange points
+                               prevPrevPoint = prevPoint;
+                               prevPoint = point;
+                       }
+               }
+       }
+
+       /**
+        * @return text description including units
+        */
+       public String getLabel()
+       {
+               return I18nManager.getText("fieldname.speed") + " ("
+                       + I18nManager.getText(_metric?"units.kmh":"units.mph") + ")";
+       }
+
+       /**
+        * @return key for message when no speeds present
+        */
+       public String getNoDataKey() {
+               return "display.notimestamps";
+       }
+}
diff --git a/tim/prune/jpeg/ExifGateway.java b/tim/prune/jpeg/ExifGateway.java
new file mode 100644 (file)
index 0000000..5420ea6
--- /dev/null
@@ -0,0 +1,80 @@
+package tim.prune.jpeg;
+
+import java.io.File;
+
+import javax.swing.JOptionPane;
+
+import tim.prune.I18nManager;
+
+/**
+ * Skeleton gateway to the Exif functions.
+ * This is required by Debian to divert Exif handling
+ * to the external libmetadata-extractor-java library
+ * instead of the included modified routines.
+ *
+ * To use the internal routines, set the USE_INTERNAL_LIBRARY flag to true
+ * and include the internal classes in the compiled jar.
+ * To use the external library, set the USE_INTERNAL_LIBRARY flag to false
+ * and do not export the internal classes.
+ */
+public abstract class ExifGateway
+{
+       // *********************************************************
+       // TODO: Check this exif library flag before releasing!
+       /** Flag to specify internal or external library */
+       private static final boolean USE_INTERNAL_LIBRARY = true;
+       // *********************************************************
+
+       /** Library object to call */
+       private static ExifLibrary _exifLibrary = null;
+       /** Flag to set whether failure warning has already been shown */
+       private static boolean _exifFailWarned = false;
+
+       /** Static block to initialise library */
+       static
+       {
+               String libraryClass = USE_INTERNAL_LIBRARY?"InternalExifLibrary":"ExternalExifLibrary";
+               try
+               {
+                       _exifLibrary = (ExifLibrary) Class.forName("tim.prune.jpeg." + libraryClass).newInstance();
+               }
+               catch (Throwable nolib) {_exifLibrary = null;}
+       }
+
+
+       /**
+        * Get the Jpeg data from the given file
+        * @param inFile file to read
+        * @return jpeg data, or null if none found
+        */
+       public static JpegData getJpegData(File inFile)
+       {
+               try
+               {
+                       // Call library (if found)
+                       if (_exifLibrary != null) {
+                               JpegData data = _exifLibrary.getJpegData(inFile);
+                               return data;
+                       }
+               }
+               catch (LinkageError nolib) {}
+               // Not successful - warn if necessary
+               if (!_exifFailWarned)
+               {
+                       JOptionPane.showMessageDialog(null, I18nManager.getText("error.jpegload.exifreadfailed"),
+                               I18nManager.getText("error.jpegload.dialogtitle"), JOptionPane.WARNING_MESSAGE);
+                       _exifFailWarned = true;
+               }
+               return null;
+       }
+
+       /**
+        * @return key to use to describe library, matching key for about dialog
+        */
+       public static String getDescriptionKey()
+       {
+               String key = USE_INTERNAL_LIBRARY?"internal":"external";
+               if (_exifLibrary == null || !_exifLibrary.looksOK()) {key = key + ".failed";}
+               return key;
+       }
+}
diff --git a/tim/prune/jpeg/ExifLibrary.java b/tim/prune/jpeg/ExifLibrary.java
new file mode 100644 (file)
index 0000000..8d00617
--- /dev/null
@@ -0,0 +1,15 @@
+package tim.prune.jpeg;
+
+import java.io.File;
+
+/**
+ * Interface satisfied by both internal and external Exif implementations
+ */
+public interface ExifLibrary
+{
+       /** Get the Jpeg data from the given file */
+       public JpegData getJpegData(File inFile);
+
+       /** Check that dependencies are resolved */
+       public boolean looksOK();
+}
diff --git a/tim/prune/jpeg/ExternalExifLibrary.java b/tim/prune/jpeg/ExternalExifLibrary.java
new file mode 100644 (file)
index 0000000..b9cd1fd
--- /dev/null
@@ -0,0 +1,120 @@
+package tim.prune.jpeg;
+
+import java.io.File;
+
+import com.drew.lang.Rational;
+import com.drew.metadata.Directory;
+import com.drew.metadata.Metadata;
+import com.drew.metadata.exif.ExifDirectory;
+import com.drew.metadata.exif.ExifReader;
+import com.drew.metadata.exif.GpsDirectory;
+
+/**
+ * Class to act as a gateway into the external exif library functions.
+ * This should be the only class with dependence on the lib-metadata-extractor-java
+ * classes (which are NOT delivered with Prune).
+ * This class will not compile without this extra dependency (but is not required if
+ * the ExifGateway uses the InternalExifLibrary instead).
+ * Should not be included if the internal library will be used (from jpeg.drew package).
+ */
+public class ExternalExifLibrary implements ExifLibrary
+{
+       /**
+        * Use the _external_ exif library to get the data from the given file
+        * @param inFile file to access
+        * @return Jpeg data if available, otherwise null
+        */
+       public JpegData getJpegData(File inFile)
+       {
+               JpegData data = new JpegData();
+               // Read exif data from picture
+               try
+               {
+                       Metadata metadata = new Metadata();
+                       new ExifReader(inFile).extract(metadata);
+                       if (metadata.containsDirectory(GpsDirectory.class))
+                       {
+                               Directory gpsdir = metadata.getDirectory(GpsDirectory.class);
+                               if (gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE)
+                                       && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE)
+                                       && gpsdir.containsTag(GpsDirectory.TAG_GPS_LATITUDE_REF)
+                                       && gpsdir.containsTag(GpsDirectory.TAG_GPS_LONGITUDE_REF))
+                               {
+                                       data.setLatitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LATITUDE_REF));
+                                       Rational[] latRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LATITUDE);
+                                       data.setLatitude(new double[] {latRats[0].doubleValue(),
+                                               latRats[1].doubleValue(), latRats[2].doubleValue()});
+                                       data.setLongitudeRef(gpsdir.getString(GpsDirectory.TAG_GPS_LONGITUDE_REF));
+                                       Rational[] lonRats = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_LONGITUDE);
+                                       data.setLongitude(new double[] {lonRats[0].doubleValue(),
+                                               lonRats[1].doubleValue(), lonRats[2].doubleValue()});
+                               }
+
+                               // Altitude (if present)
+                               if (gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE) && gpsdir.containsTag(GpsDirectory.TAG_GPS_ALTITUDE_REF))
+                               {
+                                       data.setAltitude(gpsdir.getRational(GpsDirectory.TAG_GPS_ALTITUDE).intValue());
+                                       byte altRef = (byte) gpsdir.getInt(GpsDirectory.TAG_GPS_ALTITUDE_REF);
+                                       data.setAltitudeRef(altRef);
+                               }
+
+                               // Timestamp and datestamp (if present)
+                               final int TAG_GPS_DATESTAMP = 0x001d;
+                               if (gpsdir.containsTag(GpsDirectory.TAG_GPS_TIME_STAMP) && gpsdir.containsTag(TAG_GPS_DATESTAMP))
+                               {
+                                       Rational[] times = gpsdir.getRationalArray(GpsDirectory.TAG_GPS_TIME_STAMP);
+                                       data.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(),
+                                               times[2].intValue()});
+                                       Rational[] dates = gpsdir.getRationalArray(TAG_GPS_DATESTAMP);
+                                       data.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});
+                               }
+                       }
+
+                       // Tags from Exif directory
+                       if (metadata.containsDirectory(ExifDirectory.class))
+                       {
+                               Directory exifdir = metadata.getDirectory(ExifDirectory.class);
+
+                               // Take time and date from exif tags if haven't got it already from GPS
+                               if (data.getGpsDatestamp() == null && exifdir.containsTag(ExifDirectory.TAG_DATETIME_ORIGINAL)) {
+                                       data.setOriginalTimestamp(exifdir.getString(ExifDirectory.TAG_DATETIME_ORIGINAL));
+                               }
+
+                               // Photo rotation code
+                               if (exifdir.containsTag(ExifDirectory.TAG_ORIENTATION)) {
+                                       data.setOrientationCode(exifdir.getInt(ExifDirectory.TAG_ORIENTATION));
+                                       // NOTE: this presumably takes the _last_ orientation value found, not the first.
+                               }
+
+                               // Thumbnail
+                               if (exifdir.containsTag(ExifDirectory.TAG_THUMBNAIL_DATA))
+                               {
+                                       // Make a copy of the byte data rather than keeping a reference to extracted array
+                                       byte[] tdata = exifdir.getByteArray(ExifDirectory.TAG_THUMBNAIL_DATA);
+                                       byte[] thumb = new byte[tdata.length];
+                                       System.arraycopy(tdata, 0, thumb, 0, tdata.length);
+                                       data.setThumbnailImage(thumb);
+                               }
+                       }
+
+               }
+               catch (Exception e) {
+                       // Exception reading metadata, just ignore it
+               }
+               return data;
+       }
+
+       /**
+        * Check whether the exifreader class can be correctly resolved
+        * @return true if it looks ok
+        */
+       public boolean looksOK()
+       {
+               try {
+                       String test = ExifReader.class.getName();
+                       if (test != null) return true;
+               }
+               catch (LinkageError le) {}
+               return false;
+       }
+}
diff --git a/tim/prune/jpeg/InternalExifLibrary.java b/tim/prune/jpeg/InternalExifLibrary.java
new file mode 100644 (file)
index 0000000..c8b1708
--- /dev/null
@@ -0,0 +1,42 @@
+package tim.prune.jpeg;
+
+import java.io.File;
+import tim.prune.jpeg.drew.ExifReader;
+import tim.prune.jpeg.drew.JpegException;
+
+/**
+ * Class to act as a gateway into the internal exif library functions.
+ * This should be the only class with dependence on the jpeg.drew package.
+ * Should not be included if external library will be used (eg Debian).
+ */
+public class InternalExifLibrary implements ExifLibrary
+{
+       /**
+        * Use the _internal_ exif library to get the data from the given file
+        * @param inFile file to access
+        * @return Jpeg data if available, otherwise null
+        */
+       public JpegData getJpegData(File inFile)
+       {
+               JpegData data = null;
+               try {
+                       data = new ExifReader(inFile).extract();
+               }
+               catch (JpegException jpe) {} // data remains null
+               return data;
+       }
+
+       /**
+        * Check whether the exifreader class can be correctly resolved
+        * @return true if it looks ok
+        */
+       public boolean looksOK()
+       {
+               try {
+                       String test = ExifReader.class.getName();
+                       if (test != null) return true;
+               }
+               catch (LinkageError le) {}
+               return false;
+       }
+}
similarity index 70%
rename from tim/prune/drew/jpeg/JpegData.java
rename to tim/prune/jpeg/JpegData.java
index 623fc3480709c3658c28ee74551a98af56483961..e1ed4c4753aa12c100d06f70925b57b7465f07d2 100644 (file)
@@ -1,7 +1,6 @@
-package tim.prune.drew.jpeg;
+package tim.prune.jpeg;
 
 import java.util.ArrayList;
 
 import java.util.ArrayList;
-import java.util.List;
 
 /**
  * Class to hold the GPS data extracted from a Jpeg including position and time
 
 /**
  * Class to hold the GPS data extracted from a Jpeg including position and time
@@ -12,11 +11,12 @@ public class JpegData
        private char _latitudeRef = '\0';
        private char _longitudeRef = '\0';
        private byte _altitudeRef = 0;
        private char _latitudeRef = '\0';
        private char _longitudeRef = '\0';
        private byte _altitudeRef = 0;
-       private Rational[] _latitude = null;
-       private Rational[] _longitude = null;
-       private Rational   _altitude = null;
-       private Rational[] _gpsTimestamp = null;
-       private Rational[] _gpsDatestamp = null;
+       private double[] _latitude = null;
+       private double[] _longitude = null;
+       private int _altitude = -1;
+       private boolean _altitudePresent = false;
+       private int[] _gpsTimestamp = null;
+       private int[] _gpsDatestamp = null;
        private String _originalTimestamp = null;
        private int _orientationCode = -1;
        private byte[] _thumbnail = null;
        private String _originalTimestamp = null;
        private int _orientationCode = -1;
        private byte[] _thumbnail = null;
@@ -38,15 +38,6 @@ public class JpegData
                return _exifDataPresent;
        }
 
                return _exifDataPresent;
        }
 
-       /**
-        * Set the latitude reference (N/S)
-        * @param inChar character representing reference
-        */
-       public void setLatitudeRef(char inChar)
-       {
-               _latitudeRef = inChar;
-       }
-
        /**
         * Set the latitude reference (N/S)
         * @param inString string containing reference
        /**
         * Set the latitude reference (N/S)
         * @param inString string containing reference
@@ -54,28 +45,19 @@ public class JpegData
        public void setLatitudeRef(String inString)
        {
                if (inString != null && inString.length() == 1)
        public void setLatitudeRef(String inString)
        {
                if (inString != null && inString.length() == 1)
-                       setLatitudeRef(inString.charAt(0));
+                       _latitudeRef = inString.charAt(0);
        }
 
        /**
         * Set the latitude
        }
 
        /**
         * Set the latitude
-        * @param inValues array of three Rationals for deg-min-sec
+        * @param inValues array of three doubles for deg-min-sec
         */
         */
-       public void setLatitude(Rational[] inValues)
+       public void setLatitude(double[] inValues)
        {
                if (inValues != null && inValues.length == 3)
                        _latitude = inValues;
        }
 
        {
                if (inValues != null && inValues.length == 3)
                        _latitude = inValues;
        }
 
-       /**
-        * Set the longitude reference (E/W)
-        * @param inChar character representing reference
-        */
-       public void setLongitudeRef(char inChar)
-       {
-               _longitudeRef = inChar;
-       }
-
        /**
         * Set the longitude reference (E/W)
         * @param inString string containing reference
        /**
         * Set the longitude reference (E/W)
         * @param inString string containing reference
@@ -83,14 +65,14 @@ public class JpegData
        public void setLongitudeRef(String inString)
        {
                if (inString != null && inString.length() == 1)
        public void setLongitudeRef(String inString)
        {
                if (inString != null && inString.length() == 1)
-                       setLongitudeRef(inString.charAt(0));
+                       _longitudeRef = inString.charAt(0);
        }
 
        /**
         * Set the longitude
        }
 
        /**
         * Set the longitude
-        * @param inValues array of three Rationals for deg-min-sec
+        * @param inValues array of three doubles for deg-min-sec
         */
         */
-       public void setLongitude(Rational[] inValues)
+       public void setLongitude(double[] inValues)
        {
                if (inValues != null && inValues.length == 3)
                        _longitude = inValues;
        {
                if (inValues != null && inValues.length == 3)
                        _longitude = inValues;
@@ -107,27 +89,28 @@ public class JpegData
 
        /**
         * Set the altitude
 
        /**
         * Set the altitude
-        * @param inRational Rational number representing altitude
+        * @param inValue integer representing altitude
         */
         */
-       public void setAltitude(Rational inRational)
+       public void setAltitude(int inValue)
        {
        {
-               _altitude = inRational;
+               _altitude = inValue;
+               _altitudePresent = true;
        }
 
        /**
         * Set the Gps timestamp
        }
 
        /**
         * Set the Gps timestamp
-        * @param inValues array of Rationals holding timestamp
+        * @param inValues array of ints holding timestamp
         */
         */
-       public void setGpsTimestamp(Rational[] inValues)
+       public void setGpsTimestamp(int[] inValues)
        {
                _gpsTimestamp = inValues;
        }
 
        /**
         * Set the Gps datestamp
        {
                _gpsTimestamp = inValues;
        }
 
        /**
         * Set the Gps datestamp
-        * @param inValues array of Rationals holding datestamp
+        * @param inValues array of ints holding datestamp
         */
         */
-       public void setGpsDatestamp(Rational[] inValues)
+       public void setGpsDatestamp(int[] inValues)
        {
                _gpsDatestamp = inValues;
        }
        {
                _gpsDatestamp = inValues;
        }
@@ -155,19 +138,21 @@ public class JpegData
        /** @return latitude ref as char */
        public char getLatitudeRef() { return _latitudeRef; }
        /** @return latitude as array of 3 Rationals */
        /** @return latitude ref as char */
        public char getLatitudeRef() { return _latitudeRef; }
        /** @return latitude as array of 3 Rationals */
-       public Rational[] getLatitude() { return _latitude; }
+       public double[] getLatitude() { return _latitude; }
        /** @return longitude ref as char */
        public char getLongitudeRef() { return _longitudeRef; }
        /** @return longitude ref as char */
        public char getLongitudeRef() { return _longitudeRef; }
-       /** @return longitude as array of 3 Rationals */
-       public Rational[] getLongitude() { return _longitude; }
+       /** @return longitude as array of 3 doubles */
+       public double[] getLongitude() { return _longitude; }
        /** @return altitude ref as byte (should be 0) */
        public byte getAltitudeRef() { return _altitudeRef; }
        /** @return altitude ref as byte (should be 0) */
        public byte getAltitudeRef() { return _altitudeRef; }
-       /** @return altitude as Rational */
-       public Rational getAltitude() { return _altitude; }
-       /** @return Gps timestamp as array of 3 Rationals */
-       public Rational[] getGpsTimestamp() { return _gpsTimestamp; }
-       /** @return Gps datestamp as array of 3 Rationals */
-       public Rational[] getGpsDatestamp() { return _gpsDatestamp; }
+       /** @return true if altitude present */
+       public boolean hasAltitude() { return _altitudePresent; }
+       /** @return altitude as int */
+       public int getAltitude() { return _altitude; }
+       /** @return Gps timestamp as array of 3 ints */
+       public int[] getGpsTimestamp() { return _gpsTimestamp; }
+       /** @return Gps datestamp as array of 3 ints */
+       public int[] getGpsDatestamp() { return _gpsDatestamp; }
        /** @return orientation code (1 to 8) */
        public int getOrientationCode() { return _orientationCode; }
        /** @return original timestamp as string */
        /** @return orientation code (1 to 8) */
        public int getOrientationCode() { return _orientationCode; }
        /** @return original timestamp as string */
@@ -200,7 +185,7 @@ public class JpegData
         * @return true if data looks valid, ie has at least lat and long
         *  (altitude and timestamp optional).
         */
         * @return true if data looks valid, ie has at least lat and long
         *  (altitude and timestamp optional).
         */
-       public boolean isValid()
+       public boolean isGpsValid()
        {
                return (_latitudeRef == 'N' || _latitudeRef == 'n' || _latitudeRef == 'S' || _latitudeRef == 's')
                        && _latitude != null
        {
                return (_latitudeRef == 'N' || _latitudeRef == 'n' || _latitudeRef == 'S' || _latitudeRef == 's')
                        && _latitude != null
@@ -238,7 +223,7 @@ public class JpegData
        /**
         * @return all errors as a list
         */
        /**
         * @return all errors as a list
         */
-       public List<String> getErrors()
+       public ArrayList<String> getErrors()
        {
                return _errors;
        }
        {
                return _errors;
        }
similarity index 92%
rename from tim/prune/drew/jpeg/ExifReader.java
rename to tim/prune/jpeg/drew/ExifReader.java
index 0084b87b169a6b0913f386e677c34e15aaeb757f..50a72d0caffd37c987f9897b9ec2ff2860a83994 100644 (file)
@@ -1,8 +1,10 @@
-package tim.prune.drew.jpeg;\r
+package tim.prune.jpeg.drew;\r
 \r
 import java.io.File;\r
 import java.util.HashMap;\r
 \r
 \r
 import java.io.File;\r
 import java.util.HashMap;\r
 \r
+import tim.prune.jpeg.JpegData;\r
+\r
 /**\r
  * Extracts Exif data from a JPEG header segment\r
  * Based on Drew Noakes' Metadata extractor at http://drewnoakes.com\r
 /**\r
  * Extracts Exif data from a JPEG header segment\r
  * Based on Drew Noakes' Metadata extractor at http://drewnoakes.com\r
@@ -336,25 +338,29 @@ public class ExifReader
                                inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_LATITUDE:\r
                                inMetadata.setLatitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_LATITUDE:\r
-                               inMetadata.setLatitude(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               Rational[] latitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+                               inMetadata.setLatitude(new double[] {latitudes[0].doubleValue(), latitudes[1].doubleValue(), latitudes[2].doubleValue()});\r
                                break;\r
                        case TAG_GPS_LONGITUDE_REF:\r
                                inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_LONGITUDE:\r
                                break;\r
                        case TAG_GPS_LONGITUDE_REF:\r
                                inMetadata.setLongitudeRef(readString(inTagValueOffset, inFormatCode, inComponentCount));\r
                                break;\r
                        case TAG_GPS_LONGITUDE:\r
-                               inMetadata.setLongitude(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               Rational[] longitudes = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+                               inMetadata.setLongitude(new double[] {longitudes[0].doubleValue(), longitudes[1].doubleValue(), longitudes[2].doubleValue()});\r
                                break;\r
                        case TAG_GPS_ALTITUDE_REF:\r
                                inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
                                break;\r
                        case TAG_GPS_ALTITUDE:\r
                                break;\r
                        case TAG_GPS_ALTITUDE_REF:\r
                                inMetadata.setAltitudeRef(_data[inTagValueOffset]);\r
                                break;\r
                        case TAG_GPS_ALTITUDE:\r
-                               inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               inMetadata.setAltitude(readRational(inTagValueOffset, inFormatCode, inComponentCount).intValue());\r
                                break;\r
                        case TAG_GPS_TIMESTAMP:\r
                                break;\r
                        case TAG_GPS_TIMESTAMP:\r
-                               inMetadata.setGpsTimestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               Rational[] times = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+                               inMetadata.setGpsTimestamp(new int[] {times[0].intValue(), times[1].intValue(), times[2].intValue()});\r
                                break;\r
                        case TAG_GPS_DATESTAMP:\r
                                break;\r
                        case TAG_GPS_DATESTAMP:\r
-                               inMetadata.setGpsDatestamp(readRationalArray(inTagValueOffset, inFormatCode, inComponentCount));\r
+                               Rational[] dates = readRationalArray(inTagValueOffset, inFormatCode, inComponentCount);\r
+                               inMetadata.setGpsDatestamp(new int[] {dates[0].intValue(), dates[1].intValue(), dates[2].intValue()});\r
                                break;\r
                        default: // ignore all other tags\r
                }\r
                                break;\r
                        default: // ignore all other tags\r
                }\r
similarity index 93%
rename from tim/prune/drew/jpeg/JpegException.java
rename to tim/prune/jpeg/drew/JpegException.java
index 5c757666886fac8dfb3e294a2778486dbbbda9ce..d85a3b7f1b035b75f59e9f446ed9be10f0e88f62 100644 (file)
@@ -1,4 +1,4 @@
-package tim.prune.drew.jpeg;
+package tim.prune.jpeg.drew;
 
 /**
  * Class to indicate a fatal exception processing a jpeg,
 
 /**
  * Class to indicate a fatal exception processing a jpeg,
similarity index 95%
rename from tim/prune/drew/jpeg/JpegSegmentData.java
rename to tim/prune/jpeg/drew/JpegSegmentData.java
index 8541a08b9b146eae3ce938b4b9d858b655fed890..4b56cbe9c57a6ff12a7475c5590574d114722d83 100644 (file)
@@ -1,4 +1,4 @@
-package tim.prune.drew.jpeg;\r
+package tim.prune.jpeg.drew;\r
 \r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
 \r
 import java.util.ArrayList;\r
 import java.util.HashMap;\r
similarity index 96%
rename from tim/prune/drew/jpeg/JpegSegmentReader.java
rename to tim/prune/jpeg/drew/JpegSegmentReader.java
index 20eb83c2d65f18f10588b9e18bc2e23fec463e0b..382e9f5d1e860b439aca966b9e0c87939cde542d 100644 (file)
@@ -1,4 +1,4 @@
-package tim.prune.drew.jpeg;\r
+package tim.prune.jpeg.drew;\r
 \r
 import java.io.*;\r
 \r
 \r
 import java.io.*;\r
 \r
similarity index 94%
rename from tim/prune/drew/jpeg/Rational.java
rename to tim/prune/jpeg/drew/Rational.java
index e522935159473d673b0cdf55be642e4bd78078d9..3c83b9f5d88595fadb140d4dbb4a82532d6cf495 100644 (file)
@@ -1,4 +1,4 @@
-package tim.prune.drew.jpeg;\r
+package tim.prune.jpeg.drew;\r
 \r
 /**\r
  * Immutable class for holding a rational number without loss of precision.\r
 \r
 /**\r
  * Immutable class for holding a rational number without loss of precision.\r
index 11de10f6e98214d40cee388dd7a4a54dc3417fd2..109aeb85bd7f694fe025ff14da00f50a7f55b86c 100644 (file)
@@ -3,31 +3,30 @@
 
 # Menu entries
 menu.file=L\u00eaer
 
 # Menu entries
 menu.file=L\u00eaer
-menu.file.open=Open L\u00eaer
 menu.file.addphotos=Voeg Fotos By
 menu.file.save=Stoor
 menu.file.exit=Gaan Uit
 menu.file.addphotos=Voeg Fotos By
 menu.file.save=Stoor
 menu.file.exit=Gaan Uit
-menu.edit=Redigeer
-menu.edit.undo=Herroep
-menu.edit.clearundo=Herroep Lys Skoonmaak
-menu.edit.editpoint=Redigeer Punt
-menu.edit.deletepoint=Punt Uitvee
-menu.edit.deleterange=Reeks Uitvee
-menu.edit.deletemarked=Gemerkde Punt Uitvee
-menu.edit.interpolate=Interpoleer
-menu.edit.average=Gemiddelde Seleksie
-menu.edit.reverse=Reeks Omkeer
-menu.edit.mergetracksegments=Saamvoeg van spoor segmente
-menu.edit.rearrange=Herrangskik bakens
-menu.edit.rearrange.start=Bakens na begin van l\u00eaer
-menu.edit.rearrange.end=Bakens na einde van l\u00eaer
-menu.edit.rearrange.nearest=Beweeg elk na naaste spoor punt
-menu.edit.cutandmove=Sny en skuif seleksie
-menu.select=Selekteer
-menu.select.all=Selekteer Alles
-menu.select.none=Selekteer Niks
-menu.select.start=Stel Reeks Begin
-menu.select.end=Stel Reeks Einde
+menu.track.undo=Herroep
+menu.track.clearundo=Herroep Lys Skoonmaak
+menu.point.editpoint=Redigeer Punt
+menu.point.deletepoint=Punt Uitvee
+menu.range.deleterange=Reeks Uitvee
+menu.track.deletemarked=Gemerkde Punt Uitvee
+menu.range.interpolate=Interpoleer
+menu.range.average=Gemiddelde Seleksie
+menu.range.reverse=Reeks Omkeer
+menu.range.mergetracksegments=Saamvoeg van spoor segmente
+menu.track.rearrange=Herrangskik bakens
+menu.track.rearrange.start=Bakens na begin van l\u00eaer
+menu.track.rearrange.end=Bakens na einde van l\u00eaer
+menu.track.rearrange.nearest=Beweeg elk na naaste spoor punt
+menu.range.cutandmove=Sny en skuif seleksie
+menu.range=Reeks
+menu.point=Punt
+menu.range.all=Selekteer Alles
+menu.range.none=Selekteer Niks
+menu.range.start=Stel Reeks Begin
+menu.range.end=Stel Reeks Einde
 menu.photo=Foto
 menu.photo.saveexif=Stoor na EXIF
 menu.photo.connect=Las foto by huidige punt
 menu.photo=Foto
 menu.photo.saveexif=Stoor na EXIF
 menu.photo.connect=Las foto by huidige punt
@@ -40,6 +39,7 @@ menu.view.browser.openstreetmap=Openstreetmap
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo Kaarte
 menu.view.browser.bing=Bing Kaarte
 menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo Kaarte
 menu.view.browser.bing=Bing Kaarte
+menu.settings=Stellings
 menu.help=Hulp
 # Popup menu for map
 menu.map.zoomin=Zoom in
 menu.help=Hulp
 # Popup menu for map
 menu.map.zoomin=Zoom in
@@ -50,7 +50,26 @@ menu.map.connect=Connekteer baan punte
 menu.map.autopan=Automatiese Skuif van Kyk Venster
 menu.map.showmap=Wys Kaart
 
 menu.map.autopan=Automatiese Skuif van Kyk Venster
 menu.map.showmap=Wys Kaart
 
+# Alt keys for menus
+altkey.menu.file=L
+altkey.menu.range=R
+altkey.menu.point=P
+altkey.menu.view=K
+altkey.menu.photo=F
+altkey.menu.settings=S
+altkey.menu.help=H
+
+# Ctrl shortcuts for menu items
+shortcut.menu.file.open=O
+shortcut.menu.file.load=L
+shortcut.menu.file.save=S
+shortcut.menu.track.undo=Z
+shortcut.menu.edit.compress=C
+shortcut.menu.range.all=A
+shortcut.menu.help.help=H
+
 # Functions
 # Functions
+function.open=Open L\u00eaer
 function.loadfromgps=Laai van GPS data
 function.sendtogps=Stuur van GPS data
 function.exportkml=KML Uitvoer
 function.loadfromgps=Laai van GPS data
 function.sendtogps=Stuur van GPS data
 function.exportkml=KML Uitvoer
index 26e2b659f2f03eeddd322de36aace4f2cdcf90ab..95af0aa1d584c4e610c48eb2941cad479a1aaf72 100644 (file)
@@ -3,32 +3,31 @@
 
 # Menu entries
 menu.file=Datei
 
 # Menu entries
 menu.file=Datei
-menu.file.open=Datei Ã¶ffnen
 menu.file.addphotos=Fotos laden
 menu.file.save=Speichern
 menu.file.exit=Beenden
 menu.track=Track
 menu.file.addphotos=Fotos laden
 menu.file.save=Speichern
 menu.file.exit=Beenden
 menu.track=Track
-menu.edit.undo=Rückgängig
-menu.edit.clearundo=Liste der letzten Ã„nderungen löschen
-menu.edit.editpoint=Punkt bearbeiten
-menu.edit.deletepoint=Punkt löschen
-menu.edit.deleterange=Bereich löschen
-menu.edit.deletemarked=Komprimierte Punkte löschen
-menu.edit.interpolate=Interpolieren
-menu.edit.average=Durchschnitt berechnen
-menu.edit.reverse=Bereich umkehren
-menu.edit.mergetracksegments=Trackabschnitte verbinden
-menu.edit.rearrange=Wegpunkte reorganisieren
-menu.edit.rearrange.start=Alle Wegpunkte zum Anfang
-menu.edit.rearrange.end=Alle Wegpunkte ans Ende
-menu.edit.rearrange.nearest=Jeden Wegpunkt zum nächsten Trackpunkt verschieben
-menu.edit.cutandmove=Schneiden und verschieben
+menu.track.undo=Rückgängig
+menu.track.clearundo=Liste der letzten Ã„nderungen löschen
+menu.track.deletemarked=Komprimierte Punkte löschen
+menu.track.rearrange=Wegpunkte reorganisieren
+menu.track.rearrange.start=Alle Wegpunkte zum Anfang
+menu.track.rearrange.end=Alle Wegpunkte ans Ende
+menu.track.rearrange.nearest=Jeden Wegpunkt zum nächsten Trackpunkt verschieben
 menu.range=Bereich
 menu.range=Bereich
+menu.range.all=Alles markieren
+menu.range.none=Nichts markieren
+menu.range.start=Startpunkt setzen
+menu.range.end=Endpunkt setzen
+menu.range.deleterange=Bereich löschen
+menu.range.interpolate=Interpolieren
+menu.range.average=Durchschnitt berechnen
+menu.range.reverse=Bereich umkehren
+menu.range.mergetracksegments=Trackabschnitte verbinden
+menu.range.cutandmove=Schneiden und verschieben
 menu.point=Punkt
 menu.point=Punkt
-menu.select.all=Alles markieren
-menu.select.none=Nichts markieren
-menu.select.start=Startpunkt setzen
-menu.select.end=Endpunkt setzen
+menu.point.editpoint=Punkt bearbeiten
+menu.point.deletepoint=Punkt löschen
 menu.photo=Foto
 menu.photo.saveexif=Exif Daten speichern
 menu.photo.connect=Mit Punkt verknüpfen
 menu.photo=Foto
 menu.photo.saveexif=Exif Daten speichern
 menu.photo.connect=Mit Punkt verknüpfen
@@ -37,6 +36,7 @@ menu.photo.delete=Foto entfernen
 menu.view=Ansicht
 menu.view.browser=Karte in Browser
 menu.settings=Einstellungen
 menu.view=Ansicht
 menu.view.browser=Karte in Browser
 menu.settings=Einstellungen
+menu.settings.onlinemode=Karten aus dem Internet laden
 menu.help=Hilfe
 # Popup menu for map
 menu.map.zoomin=Hineinzoomen
 menu.help=Hilfe
 # Popup menu for map
 menu.map.zoomin=Hineinzoomen
@@ -62,12 +62,13 @@ altkey.menu.help=H
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=K
 shortcut.menu.edit.compress=K
-shortcut.menu.select.all=A
+shortcut.menu.range.all=A
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=Datei Ã¶ffnen
 function.loadfromgps=Vom GPS laden
 function.sendtogps=zum GPS schicken
 function.exportkml=KML exportieren
 function.loadfromgps=Vom GPS laden
 function.sendtogps=zum GPS schicken
 function.exportkml=KML exportieren
@@ -90,6 +91,7 @@ function.setpaths=Programmpfade setzen
 function.setcolours=Farben einstellen
 function.setlanguage=Sprache einstellen
 function.getgpsies=Gpsies Tracks holen
 function.setcolours=Farben einstellen
 function.setlanguage=Sprache einstellen
 function.getgpsies=Gpsies Tracks holen
+function.lookupsrtm=Höhendaten von SRTM holen
 function.duplicatepoint=Punkt verdoppeln
 function.correlatephotos=Fotos korrelieren
 function.rearrangephotos=Fotos reorganisieren
 function.duplicatepoint=Punkt verdoppeln
 function.correlatephotos=Fotos korrelieren
 function.rearrangephotos=Fotos reorganisieren
@@ -101,6 +103,7 @@ function.showkeys=Tastenkombinationen anzeigen
 function.about=Ãœber Prune
 function.checkversion=Nach neuen Versionen suchen
 function.saveconfig=Einstellungen speichern
 function.about=Ãœber Prune
 function.checkversion=Nach neuen Versionen suchen
 function.saveconfig=Einstellungen speichern
+function.diskcache=Karten auf Disk speichern
 
 # Dialogs
 dialog.exit.confirm.title=Prune beenden
 
 # Dialogs
 dialog.exit.confirm.title=Prune beenden
@@ -126,6 +129,7 @@ dialog.openoptions.deliminfo.records=Aufnahmen, mit
 dialog.openoptions.deliminfo.fields=Feldern
 dialog.openoptions.deliminfo.norecords=Keine Rekords
 dialog.openoptions.altitudeunits=Höhe Maßeinheiten
 dialog.openoptions.deliminfo.fields=Feldern
 dialog.openoptions.deliminfo.norecords=Keine Rekords
 dialog.openoptions.altitudeunits=Höhe Maßeinheiten
+dialog.open.contentsdoubled=Diese Datei enthält zwei Kopien von jedem Punkt,\neinmal als Waypoint und einmal als Trackpunkt.
 dialog.jpegload.subdirectories=Unterordner mit durchsuchen
 dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
 dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb vom Track laden
 dialog.jpegload.subdirectories=Unterordner mit durchsuchen
 dialog.jpegload.loadjpegswithoutcoords=Auch Fotos ohne Koordinaten laden
 dialog.jpegload.loadjpegsoutsidearea=Auch Fotos ausserhalb vom Track laden
@@ -233,9 +237,14 @@ dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktueller Punkt
 dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte um die Distanzen zu berechnen
 dialog.fullrangedetails.intro=Hier sind die Details vom markierten Bereich
 dialog.distances.currentpoint=Aktueller Punkt
 dialog.distances.toofewpoints=Diese Funktion braucht Wegpunkte um die Distanzen zu berechnen
 dialog.fullrangedetails.intro=Hier sind die Details vom markierten Bereich
-dialog.setmapbg.cyclemap=Fahrradkarte
-dialog.setmapbg.other=Andere
-dialog.setmapbg.server=Server URL
+dialog.setmapbg.intro=Eine von den Quellen auswählen, oder eine neue hinzufügen
+dialog.addmapsource.title=Neue Kartequelle hinzufügen
+dialog.addmapsource.sourcename=Sourcename
+dialog.addmapsource.layer1url=URL für erste Ebene
+dialog.addmapsource.layer2url=URL für obere Ebene (falls nötig)
+dialog.addmapsource.maxzoom=Maximales Zoom
+dialog.addmapsource.cloudstyle=Stilnummer
+dialog.addmapsource.noname=Unbenannt
 dialog.gpsies.column.name=Track Name
 dialog.gpsies.column.length=Länge
 dialog.gpsies.description=Beschreibung
 dialog.gpsies.column.name=Track Name
 dialog.gpsies.column.length=Länge
 dialog.gpsies.description=Beschreibung
@@ -297,6 +306,11 @@ dialog.about.systeminfo.povray=Povray installiert
 dialog.about.systeminfo.exiftool=Exiftool installiert
 dialog.about.systeminfo.gpsbabel=Gpsbabel installiert
 dialog.about.systeminfo.gnuplot=Gnuplot installiert
 dialog.about.systeminfo.exiftool=Exiftool installiert
 dialog.about.systeminfo.gpsbabel=Gpsbabel installiert
 dialog.about.systeminfo.gnuplot=Gnuplot installiert
+dialog.about.systeminfo.exiflib=Exif Bibliothek
+dialog.about.systeminfo.exiflib.internal=Intern
+dialog.about.systeminfo.exiflib.internal.failed=Intern (nicht gefunden)
+dialog.about.systeminfo.exiflib.external=Extern
+dialog.about.systeminfo.exiflib.external.failed=Extern (nicht gefunden)
 dialog.about.yes=Ja
 dialog.about.no=Nein
 dialog.about.credits=Credits
 dialog.about.yes=Ja
 dialog.about.no=Nein
 dialog.about.credits=Credits
@@ -317,7 +331,7 @@ dialog.checkversion.releasedate1=Diese neue Version ist am
 dialog.checkversion.releasedate2=veröffentlicht worden.
 dialog.checkversion.download=Um die neue Version herunterzuladen, gehen Sie zu http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=Anstatt die Maus können Sie diesen Taste-Kombinationen nutzen
 dialog.checkversion.releasedate2=veröffentlicht worden.
 dialog.checkversion.download=Um die neue Version herunterzuladen, gehen Sie zu http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=Anstatt die Maus können Sie diesen Taste-Kombinationen nutzen
-dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + links, rechts Pfeil</td><td>Vorherigen oder nächsten Punkt markieren</td></tr><tr><td>Strg + auf, abwärts Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
+dialog.keys.keylist=<table><tr><td>Pfeil Tasten</td><td>Karte verschieben</td></tr><tr><td>Strg + links, rechts Pfeil</td><td>Vorherigen oder nächsten Punkt markieren</td></tr><tr><td>Strg + auf, abwärts Pfeil</td><td>Ein- oder Auszoomen</td></tr><tr><td>Strg + Bild auf, ab</td><td>Vorherigen oder nächsten Segment markieren</td></tr><tr><td>Strg + Pos1, Ende</td><td>Ersten oder letzten Punkt markieren</td></tr><tr><td>Entf</td><td>Aktuellen Punkt entfernen</td></tr></table>
 dialog.saveconfig.desc=Die folgende Einstellungen können gespeichert werden :
 dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
 dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
 dialog.saveconfig.desc=Die folgende Einstellungen können gespeichert werden :
 dialog.saveconfig.prune.trackdirectory=Datenverzeichnis
 dialog.saveconfig.prune.photodirectory=Fotoverzeichnis
@@ -330,13 +344,15 @@ dialog.saveconfig.prune.metricunits=Metrische Einheiten verwenden?
 dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
 dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
 dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
 dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
 dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
 dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
-dialog.saveconfig.prune.mapserverindex=Kartenserver Index
-dialog.saveconfig.prune.mapserverurl=Kartenserver URL
+dialog.saveconfig.prune.mapsource=Kartenserver Index
+dialog.saveconfig.prune.mapsourcelist=Kartenservers
+dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildhöhe in KMZ
 dialog.saveconfig.prune.colourscheme=Farbenschema
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarbe
 dialog.setpaths.intro=Sie können hier die Pfade für externe Applikationen setzen:
 dialog.saveconfig.prune.kmzimagewidth=Bildbreite in KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildhöhe in KMZ
 dialog.saveconfig.prune.colourscheme=Farbenschema
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarbe
 dialog.setpaths.intro=Sie können hier die Pfade für externe Applikationen setzen:
+dialog.setpaths.found=Pfad gefunden?
 dialog.addaltitude.noaltitudes=Der markierten Bereich enthält keine Höhenangaben
 dialog.addaltitude.desc=Höhenverschiebung aufzurechnen
 dialog.setcolours.intro=Klicken Sie auf einer Farbe um sie zu Ã¤ndern
 dialog.addaltitude.noaltitudes=Der markierten Bereich enthält keine Höhenangaben
 dialog.addaltitude.desc=Höhenverschiebung aufzurechnen
 dialog.setcolours.intro=Klicken Sie auf einer Farbe um sie zu Ã¤ndern
@@ -357,6 +373,10 @@ dialog.setlanguage.secondintro=Sie m
 dialog.setlanguage.language=Sprache
 dialog.setlanguage.languagefile=Sprache Datei
 dialog.setlanguage.endmessage=Nun speichern Sie Ihre Einstellungen und starten Sie Prune neu\num die neue Sprache zu verwenden.
 dialog.setlanguage.language=Sprache
 dialog.setlanguage.languagefile=Sprache Datei
 dialog.setlanguage.endmessage=Nun speichern Sie Ihre Einstellungen und starten Sie Prune neu\num die neue Sprache zu verwenden.
+dialog.diskcache.save=Karten zum Disk speichern
+dialog.diskcache.dir=Kartenordner
+dialog.diskcache.createdir=Ordner kreieren
+dialog.diskcache.nocreate=Ordner wurde nicht kreiert
 
 # 3d window
 dialog.3d.title=Prune 3D Ansicht
 
 # 3d window
 dialog.3d.title=Prune 3D Ansicht
@@ -393,6 +413,8 @@ confirm.correlate.multi=Fotos wurden korreliert
 confirm.createpoint=Punkt kreiert
 confirm.rotatephoto=Foto umgedreht
 confirm.running=In Bearbeitung ...
 confirm.createpoint=Punkt kreiert
 confirm.rotatephoto=Foto umgedreht
 confirm.running=In Bearbeitung ...
+confirm.lookupsrtm1=Es wurde
+confirm.lookupsrtm2=Höhenwerte gefunden
 
 # Buttons
 button.ok=OK
 
 # Buttons
 button.ok=OK
@@ -422,6 +444,8 @@ button.showwebpage=Webseite anzeigen
 button.check=Prüfen
 button.resettodefaults=Zurücksetzen
 button.browse=Durchsuchen...
 button.check=Prüfen
 button.resettodefaults=Zurücksetzen
 button.browse=Durchsuchen...
+button.addnew=Hinzufügen
+button.delete=Entfernen
 
 # File types
 filetype.txt=TXT Dateien
 
 # File types
 filetype.txt=TXT Dateien
@@ -436,6 +460,7 @@ filetype.svg=SVG Dateien
 # Display components
 display.nodata=Keine Daten geladen
 display.noaltitudes=Track enthält keine Höhenangaben
 # Display components
 display.nodata=Keine Daten geladen
 display.noaltitudes=Track enthält keine Höhenangaben
+display.notimestamps=Track enthält keine Zeitstempeln
 details.trackdetails=Details vom Track
 details.notrack=Kein Track geladen
 details.track.points=Punkte
 details.trackdetails=Details vom Track
 details.notrack=Kein Track geladen
 details.track.points=Punkte
@@ -461,6 +486,7 @@ display.range.time.hours=h
 display.range.time.days=T
 details.range.avespeed=Geschwindigkeit
 details.range.avemovingspeed=Geschwindigkeit unterwegs
 display.range.time.days=T
 details.range.avespeed=Geschwindigkeit
 details.range.avemovingspeed=Geschwindigkeit unterwegs
+details.range.maxspeed=Höchstgeschwindigkeit
 details.range.numsegments=Anzahl Abschnitte
 details.range.pace=Tempo
 details.range.gradient=Gefälle
 details.range.numsegments=Anzahl Abschnitte
 details.range.pace=Tempo
 details.range.gradient=Gefälle
@@ -535,6 +561,7 @@ undo.rearrangephotos=Fotos reorganisieren
 undo.rotatephoto=Foto umdrehen
 undo.createpoint=Punkt erzeugen
 undo.convertnamestotimes=Namen in Zeitstempeln verwandeln
 undo.rotatephoto=Foto umdrehen
 undo.createpoint=Punkt erzeugen
 undo.convertnamestotimes=Namen in Zeitstempeln verwandeln
+undo.lookupsrtm=Höhendaten von SRTM holen
 
 # Error messages
 error.save.dialogtitle=Fehler beim Speichern
 
 # Error messages
 error.save.dialogtitle=Fehler beim Speichern
@@ -558,6 +585,7 @@ error.jpegload.nofilesfound=Keine Dateien gefunden
 error.jpegload.nojpegsfound=Keine Jpeg Dateien gefunden
 error.jpegload.noexiffound=Keine EXIF Information gefunden
 error.jpegload.nogpsfound=Keine GPS Information gefunden
 error.jpegload.nojpegsfound=Keine Jpeg Dateien gefunden
 error.jpegload.noexiffound=Keine EXIF Information gefunden
 error.jpegload.nogpsfound=Keine GPS Information gefunden
+error.jpegload.exifreadfailed=EXIF Aufruf fehlgeschlagen. Keine EXIF Information können gelesen werden\nohne einen internen oder externen Bibliothek.
 error.gpsload.unknown=Unbekanntes Fehler
 error.undofailed.title=Undo fehlgeschlagen
 error.undofailed.text=Operation konnte nicht rückgängig gemacht werden
 error.gpsload.unknown=Unbekanntes Fehler
 error.undofailed.title=Undo fehlgeschlagen
 error.undofailed.text=Operation konnte nicht rückgängig gemacht werden
@@ -571,3 +599,4 @@ error.osmimage.dialogtitle=Laden von Karten-Bildern fehlgeschlagen
 error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte prüfen Sie die Internetverbindung.
 error.language.wrongfile=Die ausgewählte Datei scheint keine Sprache-Datei für Prune zu sein
 error.convertnamestotimes.nonames=Keine Namen konnten verwandelt werden
 error.osmimage.failed=Laden von Karten-Bildern fehlgeschlagen. Bitte prüfen Sie die Internetverbindung.
 error.language.wrongfile=Die ausgewählte Datei scheint keine Sprache-Datei für Prune zu sein
 error.convertnamestotimes.nonames=Keine Namen konnten verwandelt werden
+error.lookupsrtm.none=Keine Höhendaten gefunden
index 5ce66f6cd689c65d35b30b5407143cc3487c93a0..faf7db30b0f8b12f044a6fc1dd00be49a2ea828d 100644 (file)
@@ -3,32 +3,31 @@
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
-menu.file.open=File Ã¶ffne
 menu.file.addphotos=Fötelis innätue
 menu.file.save=Speichere
 menu.file.exit=Beände
 menu.track=Track
 menu.file.addphotos=Fötelis innätue
 menu.file.save=Speichere
 menu.file.exit=Beände
 menu.track=Track
-menu.edit.undo=Undo
-menu.edit.clearundo=Undo-Liste lösche
-menu.edit.editpoint=Punkt editiere
-menu.edit.deletepoint=Punkt lösche
-menu.edit.deleterange=Beriich lösche
-menu.edit.deletemarked=Komprimierte Punkte lösche
-menu.edit.interpolate=Interpoliere
-menu.edit.average=Durchschnitt uusrächne
-menu.edit.reverse=Beriich umdrähie
-menu.edit.mergetracksegments=Track Segmänte merge
-menu.edit.rearrange=Waypoints reorganisiere
-menu.edit.rearrange.start=Alli zum Aafang
-menu.edit.rearrange.end=Alli zum Ã„nde
-menu.edit.rearrange.nearest=Jede zum nöchsti Trackpunkt
-menu.edit.cutandmove=Schniide und move
+menu.track.undo=Undo
+menu.track.clearundo=Undo-Liste lösche
+menu.track.deletemarked=Komprimierte Punkte lösche
+menu.track.rearrange=Waypoints reorganisiere
+menu.track.rearrange.start=Alli zum Aafang
+menu.track.rearrange.end=Alli zum Ã„nde
+menu.track.rearrange.nearest=Jede zum nöchsti Trackpunkt
 menu.range=Beriich
 menu.range=Beriich
+menu.range.all=Alles selektiere
+menu.range.none=Nüüt selektiere
+menu.range.start=Start setzä
+menu.range.end=Stopp setzä
+menu.range.deleterange=Beriich lösche
+menu.range.interpolate=Interpoliere
+menu.range.average=Durchschnitt uusrächne
+menu.range.reverse=Beriich umdrähie
+menu.range.mergetracksegments=Track Segmänte merge
+menu.range.cutandmove=Schniide und move
 menu.point=Punkt
 menu.point=Punkt
-menu.select.all=Alles selektiere
-menu.select.none=Nüüt selektiere
-menu.select.start=Start setzä
-menu.select.end=Stopp setzä
+menu.point.editpoint=Punkt editiere
+menu.point.deletepoint=Punkt lösche
 menu.photo=Föteli
 menu.photo.saveexif=Exif Date speicherä
 menu.photo.connect=Mitem Punkt verbindä
 menu.photo=Föteli
 menu.photo.saveexif=Exif Date speicherä
 menu.photo.connect=Mitem Punkt verbindä
@@ -37,6 +36,7 @@ menu.photo.delete=F
 menu.view=Aasicht
 menu.view.browser=Karte inem Browser
 menu.settings=Iistellige
 menu.view=Aasicht
 menu.view.browser=Karte inem Browser
 menu.settings=Iistellige
+menu.settings.onlinemode=Karte uusem Internet lade
 menu.help=Hilfe
 # Popup menu for map
 menu.map.zoomin=Innezoome
 menu.help=Hilfe
 # Popup menu for map
 menu.map.zoomin=Innezoome
@@ -62,12 +62,13 @@ altkey.menu.help=H
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=K
 shortcut.menu.edit.compress=K
-shortcut.menu.select.all=A
+shortcut.menu.range.all=A
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=File Ã¶ffne
 function.loadfromgps=uusem GPS lade
 function.sendtogps=zum GPS schicke
 function.exportkml=KML exportierä
 function.loadfromgps=uusem GPS lade
 function.sendtogps=zum GPS schicke
 function.exportkml=KML exportierä
@@ -86,6 +87,7 @@ function.distances=Distanze
 function.fullrangedetails=Zuesätzlichi Beriichinfos
 function.setmapbg=Karte Hintegrund setzä
 function.getgpsies=Gpsies Tracks holä
 function.fullrangedetails=Zuesätzlichi Beriichinfos
 function.setmapbg=Karte Hintegrund setzä
 function.getgpsies=Gpsies Tracks holä
+function.lookupsrtm=Höhendate vonem SRTM hole
 function.duplicatepoint=Punkt verdopplä
 function.correlatephotos=Fötelis korrelierä
 function.rearrangephotos=Fötelis reorganisierä
 function.duplicatepoint=Punkt verdopplä
 function.correlatephotos=Fötelis korrelierä
 function.rearrangephotos=Fötelis reorganisierä
@@ -101,6 +103,7 @@ function.showkeys=Tastekombinatione aazeige
 function.about=Ãœber Prune
 function.checkversion=Pruef nach ne noie Version
 function.saveconfig=Iistellige speichere
 function.about=Ãœber Prune
 function.checkversion=Pruef nach ne noie Version
 function.saveconfig=Iistellige speichere
+function.diskcache=Karte uufem Disk speichere
 
 # Dialogs
 dialog.exit.confirm.title=Prune beände
 
 # Dialogs
 dialog.exit.confirm.title=Prune beände
@@ -126,6 +129,7 @@ dialog.openoptions.deliminfo.records=Rekords, mit
 dialog.openoptions.deliminfo.fields=Fäldere
 dialog.openoptions.deliminfo.norecords=Kei Rekords
 dialog.openoptions.altitudeunits=Höchi Masseiheite
 dialog.openoptions.deliminfo.fields=Fäldere
 dialog.openoptions.deliminfo.norecords=Kei Rekords
 dialog.openoptions.altitudeunits=Höchi Masseiheite
+dialog.open.contentsdoubled=Dieses File hät zwei Kopien von jädem Punkt,\neimol als Waypoint und eimol als Trackpunkt.
 dialog.jpegload.subdirectories=Subordnern au
 dialog.jpegload.loadjpegswithoutcoords=Au Fötelis ohni Koordinate
 dialog.jpegload.loadjpegsoutsidearea=Au Fötelis uuserhalb vonem Track
 dialog.jpegload.subdirectories=Subordnern au
 dialog.jpegload.loadjpegswithoutcoords=Au Fötelis ohni Koordinate
 dialog.jpegload.loadjpegsoutsidearea=Au Fötelis uuserhalb vonem Track
@@ -233,9 +237,14 @@ dialog.distances.column.to=Zum Punkt
 dialog.distances.currentpoint=Aktuelli Punkt
 dialog.distances.toofewpoints=d'Funktion bruucht Waypoints um die Dischtanze z berächne
 dialog.fullrangedetails.intro=Hier sind die Infos vonem aktuelli Beriich
 dialog.distances.currentpoint=Aktuelli Punkt
 dialog.distances.toofewpoints=d'Funktion bruucht Waypoints um die Dischtanze z berächne
 dialog.fullrangedetails.intro=Hier sind die Infos vonem aktuelli Beriich
-dialog.setmapbg.cyclemap=Velokarte
-dialog.setmapbg.other=Anderi
-dialog.setmapbg.server=Server URL
+dialog.setmapbg.intro=Eini von den Quällen uuswähle, oder eini neui hinzuefüge
+dialog.addmapsource.title=Neui Kartequälle hinzuefüge
+dialog.addmapsource.sourcename=Sourcename
+dialog.addmapsource.layer1url=URL für erschti Ebene
+dialog.addmapsource.layer2url=URL für oberi Ebene (falls nötig)
+dialog.addmapsource.maxzoom=Maximali Zoom
+dialog.addmapsource.cloudstyle=Stilnummere
+dialog.addmapsource.noname=Unbenannt
 dialog.gpsies.column.name=Track Name
 dialog.gpsies.column.length=Länge
 dialog.gpsies.description=Beschriebig
 dialog.gpsies.column.name=Track Name
 dialog.gpsies.column.length=Länge
 dialog.gpsies.description=Beschriebig
@@ -297,6 +306,11 @@ dialog.about.systeminfo.povray=Povray inschtalliert
 dialog.about.systeminfo.exiftool=Exiftool inschtalliert
 dialog.about.systeminfo.gpsbabel=Gpsbabel inschtalliert
 dialog.about.systeminfo.gnuplot=Gnuplot inschtalliert
 dialog.about.systeminfo.exiftool=Exiftool inschtalliert
 dialog.about.systeminfo.gpsbabel=Gpsbabel inschtalliert
 dialog.about.systeminfo.gnuplot=Gnuplot inschtalliert
+dialog.about.systeminfo.exiflib=Exif Bibliothek
+dialog.about.systeminfo.exiflib.internal=Intern
+dialog.about.systeminfo.exiflib.internal.failed=Intern (nöd gfunde)
+dialog.about.systeminfo.exiflib.external=Extärn
+dialog.about.systeminfo.exiflib.external.failed=Extärn (nöd gfunde)
 dialog.about.yes=Ja
 dialog.about.no=Nei
 dialog.about.credits=Credits
 dialog.about.yes=Ja
 dialog.about.no=Nei
 dialog.about.credits=Credits
@@ -317,7 +331,7 @@ dialog.checkversion.releasedate1=Die noii Version isch am
 dialog.checkversion.releasedate2=ussecho.
 dialog.checkversion.download=Um die noii Version runterzlade, schauet Sie na http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=Aastatt d'Muus könnet Sie diese Tastekombinationen nutze
 dialog.checkversion.releasedate2=ussecho.
 dialog.checkversion.download=Um die noii Version runterzlade, schauet Sie na http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=Aastatt d'Muus könnet Sie diese Tastekombinationen nutze
-dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, rächts Pfiil</td><td>Vorherigi oder nöchsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Entf</td><td>Aktuelli Punkt lösche</td></tr></table>
+dialog.keys.keylist=<table><tr><td>Pfiil Taste</td><td>Karte verschiebe</td></tr><tr><td>Strg + links, rächts Pfiil</td><td>Vorherigi oder nöchsti Punkt markiere</td></tr><tr><td>Strg + uuf, aba Pfiil</td><td>Ii- oder Uusezoome</td></tr><tr><td>Strg + Bild uuf, ab</td><td>Vorherigi oder nöchsti Segmänt markiere</td></tr><tr><td>Strg + Pos1, Ende</td><td>Erschti oder letschti Punkt markiere</td></tr><tr><td>Entf</td><td>Aktuelli Punkt lösche</td></tr></table>
 dialog.saveconfig.desc=Die folgendi Iinstellige könne gspeicheret werde :
 dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
 dialog.saveconfig.prune.photodirectory=Föteliverzeichnis
 dialog.saveconfig.desc=Die folgendi Iinstellige könne gspeicheret werde :
 dialog.saveconfig.prune.trackdirectory=Trackverzeichnis
 dialog.saveconfig.prune.photodirectory=Föteliverzeichnis
@@ -330,13 +344,15 @@ dialog.saveconfig.prune.metricunits=Metrischi Einheite verwende?
 dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
 dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
 dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
 dialog.saveconfig.prune.gnuplotpath=Gnuplot Pfad
 dialog.saveconfig.prune.gpsbabelpath=Gpsbabel Pfad
 dialog.saveconfig.prune.exiftoolpath=Exiftool Pfad
-dialog.saveconfig.prune.mapserverindex=Kartenserver Index
-dialog.saveconfig.prune.mapserverurl=Kartenserver URL
+dialog.saveconfig.prune.mapsource=Kartenserver Index
+dialog.saveconfig.prune.mapsourcelist=Kartenservers
+dialog.saveconfig.prune.diskcache=Kartenordner
 dialog.saveconfig.prune.kmzimagewidth=Bildbreiti im KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildhöchi im KMZ
 dialog.saveconfig.prune.colourscheme=Farbeschema
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarb
 dialog.setpaths.intro=Sie könnet dann die Pfade für dia Applikatione setzä:
 dialog.saveconfig.prune.kmzimagewidth=Bildbreiti im KMZ
 dialog.saveconfig.prune.kmzimageheight=Bildhöchi im KMZ
 dialog.saveconfig.prune.colourscheme=Farbeschema
 dialog.saveconfig.prune.kmltrackcolour=KML Trackfarb
 dialog.setpaths.intro=Sie könnet dann die Pfade für dia Applikatione setzä:
+dialog.setpaths.found=Pfad gfunde?
 dialog.addaltitude.noaltitudes=Dr seläktierte Beriich hät keini Höchiinformation
 dialog.addaltitude.desc=Höchiverschiebig zuzutue
 dialog.setcolours.intro=Klicket Sie uuf ne Farb um sie z'verändere
 dialog.addaltitude.noaltitudes=Dr seläktierte Beriich hät keini Höchiinformation
 dialog.addaltitude.desc=Höchiverschiebig zuzutue
 dialog.setcolours.intro=Klicket Sie uuf ne Farb um sie z'verändere
@@ -357,6 +373,10 @@ dialog.setlanguage.secondintro=Sie m
 dialog.setlanguage.language=Sproch
 dialog.setlanguage.languagefile=Sproch Datei
 dialog.setlanguage.endmessage=Jetze speicheret Sie Ihri Iistellige und startet Sie Prune neu\num t noii Sproch z' verwände.
 dialog.setlanguage.language=Sproch
 dialog.setlanguage.languagefile=Sproch Datei
 dialog.setlanguage.endmessage=Jetze speicheret Sie Ihri Iistellige und startet Sie Prune neu\num t noii Sproch z' verwände.
+dialog.diskcache.save=Karten uufem Disk speichere
+dialog.diskcache.dir=Kartenordner
+dialog.diskcache.createdir=Ordner kreiere
+dialog.diskcache.nocreate=Ordner isch nöd kreiert worde
 
 # 3d window
 dialog.3d.title=Prune Drüü-d Aasicht
 
 # 3d window
 dialog.3d.title=Prune Drüü-d Aasicht
@@ -393,6 +413,8 @@ confirm.correlate.multi=F
 confirm.createpoint=Punkt kreiert worde
 confirm.rotatephoto=Föteli umgedräit worde
 confirm.running=Am Laufe ...
 confirm.createpoint=Punkt kreiert worde
 confirm.rotatephoto=Föteli umgedräit worde
 confirm.running=Am Laufe ...
+confirm.lookupsrtm1=Es sin
+confirm.lookupsrtm2=Höhenwerte gfunde
 
 # Buttons
 button.ok=OK
 
 # Buttons
 button.ok=OK
@@ -422,6 +444,8 @@ button.showwebpage=Websiite aazeig
 button.check=Prüefa
 button.resettodefaults=Zurücksetzä
 button.browse=Durasuechä...
 button.check=Prüefa
 button.resettodefaults=Zurücksetzä
 button.browse=Durasuechä...
+button.addnew=Hinzuefügä
+button.delete=Entfärnä
 
 # File types
 filetype.txt=TXT Dateie
 
 # File types
 filetype.txt=TXT Dateie
@@ -436,6 +460,7 @@ filetype.svg=SVG Dateie
 # Display components
 display.nodata=Kei Date glade worde
 display.noaltitudes=Track hät kei Höhi Date
 # Display components
 display.nodata=Kei Date glade worde
 display.noaltitudes=Track hät kei Höhi Date
+display.notimestamps=Track hät kei Ziitstämple
 details.trackdetails=Details vom Track
 details.notrack=Kei Track glade worde
 details.track.points=Punkte
 details.trackdetails=Details vom Track
 details.notrack=Kei Track glade worde
 details.track.points=Punkte
@@ -461,6 +486,7 @@ display.range.time.hours=Std
 display.range.time.days=T
 details.range.avespeed=Gschwindikeit
 details.range.avemovingspeed=Gschwindikeit ufem Wäg
 display.range.time.days=T
 details.range.avespeed=Gschwindikeit
 details.range.avemovingspeed=Gschwindikeit ufem Wäg
+details.range.maxspeed=Höchstgschwindikeit
 details.range.numsegments=Aazahl Segmänte
 details.range.pace=Tempo
 details.range.gradient=Gefälle
 details.range.numsegments=Aazahl Segmänte
 details.range.pace=Tempo
 details.range.gradient=Gefälle
@@ -535,6 +561,7 @@ undo.rearrangephotos=F
 undo.createpoint=Punkt kreierä
 undo.rotatephoto=Föteli umadräya
 undo.convertnamestotimes=Name ins Ziitstämple verwondlä
 undo.createpoint=Punkt kreierä
 undo.rotatephoto=Föteli umadräya
 undo.convertnamestotimes=Name ins Ziitstämple verwondlä
+undo.lookupsrtm=Höhendate vonem SRTM hole
 
 # Error messages
 error.save.dialogtitle=Fähle bim Speichere
 
 # Error messages
 error.save.dialogtitle=Fähle bim Speichere
@@ -558,6 +585,7 @@ error.jpegload.nofilesfound=Kei Dateie gfunde
 error.jpegload.nojpegsfound=Kei Jpegs gfunde
 error.jpegload.noexiffound=Kei EXIF Information gfunde
 error.jpegload.nogpsfound=Kei GPS Information gfunde
 error.jpegload.nojpegsfound=Kei Jpegs gfunde
 error.jpegload.noexiffound=Kei EXIF Information gfunde
 error.jpegload.nogpsfound=Kei GPS Information gfunde
+error.jpegload.exifreadfailed=EXIF Uufruef isch fehlgschlage. Kei EXIF Infos könnet gläse werde\nohni nen interni oder extärni Bibliothek.
 error.gpsload.unknown=Unbekannts Fähler
 error.undofailed.title=Undo isch fehlgschlage worde
 error.undofailed.text=Operation kann nöd rückgängig gmacht werde
 error.gpsload.unknown=Unbekannts Fähler
 error.undofailed.title=Undo isch fehlgschlage worde
 error.undofailed.text=Operation kann nöd rückgängig gmacht werde
@@ -571,3 +599,4 @@ error.osmimage.dialogtitle=F
 error.osmimage.failed=Map Bildli könne nöd glade werde.  Gits ne Internet Verbindig?
 error.language.wrongfile=Die uusgewählti Datei scheint kei Sproch-Datei für Prune z'sii
 error.convertnamestotimes.nonames=Kei Namen han könnet verwondlet werde
 error.osmimage.failed=Map Bildli könne nöd glade werde.  Gits ne Internet Verbindig?
 error.language.wrongfile=Die uusgewählti Datei scheint kei Sproch-Datei für Prune z'sii
 error.convertnamestotimes.nonames=Kei Namen han könnet verwondlet werde
+error.lookupsrtm.none=Kei Höhendate gfunde
index 47ccdc68496c989551d40bc9c9c8eab09584d5f6..d92a98a674282cf52415597a79dcfad224b4c0de 100644 (file)
@@ -3,32 +3,31 @@
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
-menu.file.open=Open file
 menu.file.addphotos=Add photos
 menu.file.save=Save
 menu.file.exit=Exit
 menu.track=Track
 menu.file.addphotos=Add photos
 menu.file.save=Save
 menu.file.exit=Exit
 menu.track=Track
-menu.edit.undo=Undo
-menu.edit.clearundo=Clear undo list
-menu.edit.editpoint=Edit point
-menu.edit.deletepoint=Delete point
-menu.edit.deleterange=Delete range
-menu.edit.deletemarked=Delete marked points
-menu.edit.interpolate=Interpolate
-menu.edit.average=Average selection
-menu.edit.reverse=Reverse range
-menu.edit.mergetracksegments=Merge track segments
-menu.edit.rearrange=Rearrange waypoints
-menu.edit.rearrange.start=All to start of file
-menu.edit.rearrange.end=All to end of file
-menu.edit.rearrange.nearest=Each to nearest track point
-menu.edit.cutandmove=Cut and move selection
+menu.track.undo=Undo
+menu.track.clearundo=Clear undo list
+menu.track.deletemarked=Delete marked points
+menu.track.rearrange=Rearrange waypoints
+menu.track.rearrange.start=All to start of file
+menu.track.rearrange.end=All to end of file
+menu.track.rearrange.nearest=Each to nearest track point
 menu.range=Range
 menu.range=Range
+menu.range.all=Select all
+menu.range.none=Select none
+menu.range.start=Set range start
+menu.range.end=Set range end
+menu.range.deleterange=Delete range
+menu.range.interpolate=Interpolate
+menu.range.average=Average selection
+menu.range.reverse=Reverse range
+menu.range.mergetracksegments=Merge track segments
+menu.range.cutandmove=Cut and move selection
 menu.point=Point
 menu.point=Point
-menu.select.all=Select all
-menu.select.none=Select none
-menu.select.start=Set range start
-menu.select.end=Set range end
+menu.point.editpoint=Edit point
+menu.point.deletepoint=Delete point
 menu.photo=Photo
 menu.photo.saveexif=Save to Exif
 menu.photo.connect=Connect to point
 menu.photo=Photo
 menu.photo.saveexif=Save to Exif
 menu.photo.connect=Connect to point
@@ -42,6 +41,7 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Bing maps
 menu.settings=Settings
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Bing maps
 menu.settings=Settings
+menu.settings.onlinemode=Load maps from internet
 menu.help=Help
 # Popup menu for map
 menu.map.zoomin=Zoom in
 menu.help=Help
 # Popup menu for map
 menu.map.zoomin=Zoom in
@@ -67,12 +67,13 @@ altkey.menu.help=H
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=A
+shortcut.menu.range.all=A
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=Open file
 function.loadfromgps=Load data from GPS
 function.sendtogps=Send data to GPS
 function.exportkml=Export KML
 function.loadfromgps=Load data from GPS
 function.sendtogps=Send data to GPS
 function.exportkml=Export KML
@@ -90,6 +91,7 @@ function.show3d=Three-D view
 function.distances=Distances
 function.fullrangedetails=Full range details
 function.getgpsies=Get Gpsies tracks
 function.distances=Distances
 function.fullrangedetails=Full range details
 function.getgpsies=Get Gpsies tracks
+function.lookupsrtm=Get altitudes from SRTM
 function.duplicatepoint=Duplicate point
 function.correlatephotos=Correlate photos
 function.rearrangephotos=Rearrange photos
 function.duplicatepoint=Duplicate point
 function.correlatephotos=Correlate photos
 function.rearrangephotos=Rearrange photos
@@ -106,6 +108,7 @@ function.showkeys=Show shortcut keys
 function.about=About Prune
 function.checkversion=Check for new version
 function.saveconfig=Save settings
 function.about=About Prune
 function.checkversion=Check for new version
 function.saveconfig=Save settings
+function.diskcache=Save maps to disk
 
 # Dialogs
 dialog.exit.confirm.title=Exit Prune
 
 # Dialogs
 dialog.exit.confirm.title=Exit Prune
@@ -131,6 +134,7 @@ dialog.openoptions.deliminfo.records=records, with
 dialog.openoptions.deliminfo.fields=fields
 dialog.openoptions.deliminfo.norecords=No records
 dialog.openoptions.altitudeunits=Altitude units
 dialog.openoptions.deliminfo.fields=fields
 dialog.openoptions.deliminfo.norecords=No records
 dialog.openoptions.altitudeunits=Altitude units
+dialog.open.contentsdoubled=This file contains two copies of each point,\nonce as waypoints and once as track points.
 dialog.jpegload.subdirectories=Include subdirectories
 dialog.jpegload.loadjpegswithoutcoords=Include photos without coordinates
 dialog.jpegload.loadjpegsoutsidearea=Include photos outside current area
 dialog.jpegload.subdirectories=Include subdirectories
 dialog.jpegload.loadjpegswithoutcoords=Include photos without coordinates
 dialog.jpegload.loadjpegsoutsidearea=Include photos outside current area
@@ -238,11 +242,14 @@ dialog.distances.column.to=To point
 dialog.distances.currentpoint=Current point
 dialog.distances.toofewpoints=This function needs waypoints in order to calculate the distances between them
 dialog.fullrangedetails.intro=Here are the details for the selected range
 dialog.distances.currentpoint=Current point
 dialog.distances.toofewpoints=This function needs waypoints in order to calculate the distances between them
 dialog.fullrangedetails.intro=Here are the details for the selected range
-dialog.setmapbg.mapnik=Mapnik (default)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=Other
-dialog.setmapbg.server=Server URL
+dialog.setmapbg.intro=Select one of the map sources, or add a new one
+dialog.addmapsource.title=Add new map source
+dialog.addmapsource.sourcename=Name of source
+dialog.addmapsource.layer1url=URL of first layer
+dialog.addmapsource.layer2url=Optional URL of second layer
+dialog.addmapsource.maxzoom=Maximum zoom level
+dialog.addmapsource.cloudstyle=Style number
+dialog.addmapsource.noname=Unnamed
 dialog.gpsies.column.name=Track name
 dialog.gpsies.column.length=Length
 dialog.gpsies.description=Description
 dialog.gpsies.column.name=Track name
 dialog.gpsies.column.length=Length
 dialog.gpsies.description=Description
@@ -304,6 +311,11 @@ dialog.about.systeminfo.povray=Povray installed
 dialog.about.systeminfo.exiftool=Exiftool installed
 dialog.about.systeminfo.gpsbabel=Gpsbabel installed
 dialog.about.systeminfo.gnuplot=Gnuplot installed
 dialog.about.systeminfo.exiftool=Exiftool installed
 dialog.about.systeminfo.gpsbabel=Gpsbabel installed
 dialog.about.systeminfo.gnuplot=Gnuplot installed
+dialog.about.systeminfo.exiflib=Exif library
+dialog.about.systeminfo.exiflib.internal=Internal
+dialog.about.systeminfo.exiflib.internal.failed=Internal (not found)
+dialog.about.systeminfo.exiflib.external=External
+dialog.about.systeminfo.exiflib.external.failed=External (not found)
 dialog.about.yes=Yes
 dialog.about.no=No
 dialog.about.credits=Credits
 dialog.about.yes=Yes
 dialog.about.no=No
 dialog.about.credits=Credits
@@ -324,7 +336,7 @@ dialog.checkversion.releasedate1=This new version was released on
 dialog.checkversion.releasedate2=.
 dialog.checkversion.download=To download the new version, go to http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=You can use the following shortcut keys instead of using the mouse
 dialog.checkversion.releasedate2=.
 dialog.checkversion.download=To download the new version, go to http://activityworkshop.net/software/prune/download.html.
 dialog.keys.intro=You can use the following shortcut keys instead of using the mouse
-dialog.keys.keylist=<table><tr><td>Arrow keys</td><td>Pan map left right, up, down</td></tr><tr><td>Ctrl + left, right arrow</td><td>Select previous or next point</td></tr><tr><td>Ctrl + up, down arrow</td><td>Zoom in or out</td></tr><tr><td>Del</td><td>Delete current point</td></tr></table>
+dialog.keys.keylist=<table><tr><td>Arrow keys</td><td>Pan map left right, up, down</td></tr><tr><td>Ctrl + left, right arrow</td><td>Select previous or next point</td></tr><tr><td>Ctrl + up, down arrow</td><td>Zoom in or out</td></tr><tr><td>Ctrl + PgUp, PgDown</td><td>Select previous, next segment</td></tr><tr><td>Ctrl + Home, End</td><td>Select first, last point</td></tr><tr><td>Del</td><td>Delete current point</td></tr></table>
 dialog.saveconfig.desc=The following settings can be saved to a configuration file :
 dialog.saveconfig.prune.trackdirectory=Track directory
 dialog.saveconfig.prune.photodirectory=Photo directory
 dialog.saveconfig.desc=The following settings can be saved to a configuration file :
 dialog.saveconfig.prune.trackdirectory=Track directory
 dialog.saveconfig.prune.photodirectory=Photo directory
@@ -337,13 +349,15 @@ dialog.saveconfig.prune.metricunits=Use metric units?
 dialog.saveconfig.prune.gnuplotpath=Path to gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Path to gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path to exiftool
 dialog.saveconfig.prune.gnuplotpath=Path to gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Path to gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path to exiftool
-dialog.saveconfig.prune.mapserverindex=Index of map server
-dialog.saveconfig.prune.mapserverurl=URL of map server
+dialog.saveconfig.prune.mapsource=Selected map source
+dialog.saveconfig.prune.mapsourcelist=Map sources
+dialog.saveconfig.prune.diskcache=Map cache
 dialog.saveconfig.prune.kmzimagewidth=KMZ image width
 dialog.saveconfig.prune.kmzimageheight=KMZ image height
 dialog.saveconfig.prune.colourscheme=Colour scheme
 dialog.saveconfig.prune.kmltrackcolour=KML track colour
 dialog.setpaths.intro=If you need to, you can choose the paths to the external applications:
 dialog.saveconfig.prune.kmzimagewidth=KMZ image width
 dialog.saveconfig.prune.kmzimageheight=KMZ image height
 dialog.saveconfig.prune.colourscheme=Colour scheme
 dialog.saveconfig.prune.kmltrackcolour=KML track colour
 dialog.setpaths.intro=If you need to, you can choose the paths to the external applications:
+dialog.setpaths.found=Path found?
 dialog.addaltitude.noaltitudes=The selected range does not contain altitudes
 dialog.addaltitude.desc=Altitude offset to add
 dialog.setcolours.intro=Click on a colour patch to change the colour
 dialog.addaltitude.noaltitudes=The selected range does not contain altitudes
 dialog.addaltitude.desc=Altitude offset to add
 dialog.setcolours.intro=Click on a colour patch to change the colour
@@ -364,6 +378,10 @@ dialog.setlanguage.secondintro=You need to save your settings and then<p>restart
 dialog.setlanguage.language=Language
 dialog.setlanguage.languagefile=Language file
 dialog.setlanguage.endmessage=Now save your settings and restart Prune\nfor the language change to take effect.
 dialog.setlanguage.language=Language
 dialog.setlanguage.languagefile=Language file
 dialog.setlanguage.endmessage=Now save your settings and restart Prune\nfor the language change to take effect.
+dialog.diskcache.save=Save map images to disk
+dialog.diskcache.dir=Cache directory
+dialog.diskcache.createdir=Create directory
+dialog.diskcache.nocreate=Cache directory not created
 
 # 3d window
 dialog.3d.title=Prune Three-d view
 
 # 3d window
 dialog.3d.title=Prune Three-d view
@@ -400,6 +418,8 @@ confirm.correlate.multi=photos were correlated
 confirm.rotatephoto=photo rotated
 confirm.createpoint=point created
 confirm.running=Running ...
 confirm.rotatephoto=photo rotated
 confirm.createpoint=point created
 confirm.running=Running ...
+confirm.lookupsrtm1=Found
+confirm.lookupsrtm2=altitude values
 
 # Buttons
 button.ok=OK
 
 # Buttons
 button.ok=OK
@@ -429,6 +449,8 @@ button.showwebpage=Show webpage
 button.check=Check
 button.resettodefaults=Reset to defaults
 button.browse=Browse...
 button.check=Check
 button.resettodefaults=Reset to defaults
 button.browse=Browse...
+button.addnew=Add new
+button.delete=Delete
 
 # File types
 filetype.txt=TXT files
 
 # File types
 filetype.txt=TXT files
@@ -443,6 +465,7 @@ filetype.svg=SVG files
 # Display components
 display.nodata=No data loaded
 display.noaltitudes=Track data does not include altitudes
 # Display components
 display.nodata=No data loaded
 display.noaltitudes=Track data does not include altitudes
+display.notimestamps=Track data does not include timestamps
 details.trackdetails=Track details
 details.notrack=No track loaded
 details.track.points=Points
 details.trackdetails=Track details
 details.notrack=No track loaded
 details.track.points=Points
@@ -467,7 +490,8 @@ display.range.time.mins=m
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Ave speed
 display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Ave speed
-details.range.avemovingspeed=Moving ave
+details.range.avemovingspeed=Moving average
+details.range.maxspeed=Maximum speed
 details.range.numsegments=Number of segments
 details.range.pace=Pace
 details.range.gradient=Gradient
 details.range.numsegments=Number of segments
 details.range.pace=Pace
 details.range.gradient=Gradient
@@ -548,6 +572,7 @@ undo.rearrangephotos=rearrange photos
 undo.rotatephoto=rotate photo
 undo.createpoint=create point
 undo.convertnamestotimes=convert names to times
 undo.rotatephoto=rotate photo
 undo.createpoint=create point
 undo.convertnamestotimes=convert names to times
+undo.lookupsrtm=lookup altitudes from SRTM
 
 # Error messages
 error.save.dialogtitle=Error saving data
 
 # Error messages
 error.save.dialogtitle=Error saving data
@@ -571,6 +596,7 @@ error.jpegload.nofilesfound=No files found
 error.jpegload.nojpegsfound=No jpeg files found
 error.jpegload.noexiffound=No EXIF information found
 error.jpegload.nogpsfound=No GPS information found
 error.jpegload.nojpegsfound=No jpeg files found
 error.jpegload.noexiffound=No EXIF information found
 error.jpegload.nogpsfound=No GPS information found
+error.jpegload.exifreadfailed=Failed to read EXIF information. No EXIF information can be read\nwithout either an internal or external library.
 error.gpsload.unknown=Unknown error
 error.undofailed.title=Undo failed
 error.undofailed.text=Failed to undo operation
 error.gpsload.unknown=Unknown error
 error.undofailed.title=Undo failed
 error.undofailed.text=Failed to undo operation
@@ -584,3 +610,4 @@ error.osmimage.dialogtitle=Error loading map images
 error.osmimage.failed=Failed to load map images. Please check internet connection.
 error.language.wrongfile=The selected file doesn't appear to be a language file for Prune
 error.convertnamestotimes.nonames=No names could be converted into times
 error.osmimage.failed=Failed to load map images. Please check internet connection.
 error.language.wrongfile=The selected file doesn't appear to be a language file for Prune
 error.convertnamestotimes.nonames=No names could be converted into times
+error.lookupsrtm.none=No altitude values found
index e610064ccb12233c91496da4991cc03b89e2aca7..a54ee1b2ecb4bad853899ec08635209d050574be 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=Archivo
 
 # Menu entries
 menu.file=Archivo
-menu.file.open=Abrir archivo
 menu.file.addphotos=Cargar fotos
 menu.file.save=Guardar
 menu.file.exit=Salir
 menu.file.addphotos=Cargar fotos
 menu.file.save=Guardar
 menu.file.exit=Salir
-menu.edit=Editar
 menu.track=Track
 menu.track=Track
-menu.edit.undo=Deshacer
-menu.edit.clearundo=Despejar la lista de deshacer
-menu.edit.editpoint=Editar punto
-menu.edit.deletepoint=Eliminar punto
-menu.edit.deleterange=Eliminar rango
-menu.edit.deletemarked=Eliminar puntos marcados
-menu.edit.interpolate=Interpolar
-menu.edit.average=Crear punto a la media del rango
-menu.edit.reverse=Invertir rango
-menu.edit.mergetracksegments=Unir los segmentos de track
-menu.edit.rearrange=Reorganizar waypoints
-menu.edit.rearrange.start=Volver al comienzo
-menu.edit.rearrange.end=Ir al final
-menu.edit.rearrange.nearest=Ir al m\u00e1s pr\u00f3ximo
-menu.edit.cutandmove=Cortar y mover selecci\u00f3n
-menu.select=Seleccionar
+menu.track.undo=Deshacer
+menu.track.clearundo=Despejar la lista de deshacer
+menu.track.deletemarked=Eliminar puntos marcados
+menu.track.rearrange=Reorganizar waypoints
+menu.track.rearrange.start=Volver al comienzo
+menu.track.rearrange.end=Ir al final
+menu.track.rearrange.nearest=Ir al m\u00e1s pr\u00f3ximo
 menu.range=Rango
 menu.range=Rango
+menu.range.all=Seleccionar todo
+menu.range.none=No seleccionar nada
+menu.range.start=Fijar comienzo
+menu.range.end=Fijar final
+menu.range.deleterange=Eliminar rango
+menu.range.interpolate=Interpolar
+menu.range.average=Crear punto a la media del rango
+menu.range.reverse=Invertir rango
+menu.range.mergetracksegments=Unir los segmentos de track
+menu.range.cutandmove=Cortar y mover selecci\u00f3n
 menu.point=Punto
 menu.point=Punto
-menu.select.all=Seleccionar todo
-menu.select.none=No seleccionar nada
-menu.select.start=Fijar comienzo
-menu.select.end=Fijar final
+menu.point.editpoint=Editar punto
+menu.point.deletepoint=Eliminar punto
 menu.photo=Foto
 menu.photo.saveexif=Guardar Exif
 menu.photo.connect=Conectar con punto
 menu.photo=Foto
 menu.photo.saveexif=Guardar Exif
 menu.photo.connect=Conectar con punto
@@ -57,8 +54,6 @@ menu.map.showscalebar=Mostrar barra de escala
 
 # Alt keys for menus
 altkey.menu.file=A
 
 # Alt keys for menus
 altkey.menu.file=A
-altkey.menu.edit=E
-altkey.menu.select=S
 altkey.menu.track=T
 altkey.menu.range=R
 altkey.menu.point=U
 altkey.menu.track=T
 altkey.menu.range=R
 altkey.menu.point=U
@@ -71,12 +66,13 @@ altkey.menu.help=Y
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=G
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=G
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=T
+shortcut.menu.range.all=T
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=Abrir archivo
 function.loadfromgps=Cargar datos del GPS
 function.sendtogps=Enviar datos al GPS
 function.exportkml=Exportar KML
 function.loadfromgps=Cargar datos del GPS
 function.sendtogps=Enviar datos al GPS
 function.exportkml=Exportar KML
@@ -214,8 +210,6 @@ dialog.addtimeoffset.minutes=Minutos
 dialog.addtimeoffset.notimestamps=No se puede a\u00f1adir tiempo de puesta a esta selecci\u00f3n si \u00e9sta no contiene ninguna informaci\u00f3n de "timestamp"
 dialog.findwaypoint.intro=Ingresar parte del nombre de "waypoint"
 dialog.findwaypoint.search=Buscar
 dialog.addtimeoffset.notimestamps=No se puede a\u00f1adir tiempo de puesta a esta selecci\u00f3n si \u00e9sta no contiene ninguna informaci\u00f3n de "timestamp"
 dialog.findwaypoint.intro=Ingresar parte del nombre de "waypoint"
 dialog.findwaypoint.search=Buscar
-dialog.connect.title=Conectar foto
-dialog.connectphoto.clonepoint=Este punto ya tiene una foto.\n Quisiera usted hacer una copia de este?
 dialog.saveexif.title=Guardar Exif
 dialog.saveexif.intro=Seleccione fotos a guardar
 dialog.saveexif.nothingtosave=Coordenadas no modificadas, nada que guardar
 dialog.saveexif.title=Guardar Exif
 dialog.saveexif.intro=Seleccione fotos a guardar
 dialog.saveexif.nothingtosave=Coordenadas no modificadas, nada que guardar
@@ -243,9 +237,9 @@ dialog.distances.column.to=Al punto
 dialog.distances.currentpoint=Punto actual
 dialog.distances.toofewpoints=Esta funcion necesita "waypoints" para poder calcular las distancias entre ellos
 dialog.fullrangedetails.intro=Aqui estan los detalles para la selecci\u00f3n de rangos
 dialog.distances.currentpoint=Punto actual
 dialog.distances.toofewpoints=Esta funcion necesita "waypoints" para poder calcular las distancias entre ellos
 dialog.fullrangedetails.intro=Aqui estan los detalles para la selecci\u00f3n de rangos
-dialog.setmapbg.mapnik=Mapnik (predeterminado)
-dialog.setmapbg.other=Otro
-dialog.setmapbg.server=Direcci\u00f3n URL del servidor
+dialog.addmapsource.sourcename=Nombre de la fuente
+dialog.addmapsource.cloudstyle=N\u00famero del estilo
+dialog.addmapsource.noname=Innominada
 dialog.gpsies.column.name=Nombre del track
 dialog.gpsies.column.length=Distancia
 dialog.gpsies.description=Descripci\u00f3n
 dialog.gpsies.column.name=Nombre del track
 dialog.gpsies.column.length=Distancia
 dialog.gpsies.description=Descripci\u00f3n
@@ -304,6 +298,11 @@ dialog.about.systeminfo.povray=Povray instalado
 dialog.about.systeminfo.exiftool=Exiftool instalado
 dialog.about.systeminfo.gpsbabel=Gpsbabel instalado
 dialog.about.systeminfo.gnuplot=Gnuplot instalado
 dialog.about.systeminfo.exiftool=Exiftool instalado
 dialog.about.systeminfo.gpsbabel=Gpsbabel instalado
 dialog.about.systeminfo.gnuplot=Gnuplot instalado
+dialog.about.systeminfo.exiflib=Bibliotheca exif
+dialog.about.systeminfo.exiflib.internal=Interna
+dialog.about.systeminfo.exiflib.internal.failed=Interna (no encontrada)
+dialog.about.systeminfo.exiflib.external=Externa
+dialog.about.systeminfo.exiflib.external.failed=Externa (no encontrada)
 dialog.about.yes=Si
 dialog.about.no=No
 dialog.about.credits=Creditos
 dialog.about.yes=Si
 dialog.about.no=No
 dialog.about.credits=Creditos
@@ -337,6 +336,8 @@ dialog.saveconfig.prune.gpsbabelpath=Camino a gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Camino a exiftool
 dialog.saveconfig.prune.mapserverindex=\u00cdndice de mapa del servidor
 dialog.saveconfig.prune.mapserverurl=Direcci\u00f3n URL de mapa del servidor
 dialog.saveconfig.prune.exiftoolpath=Camino a exiftool
 dialog.saveconfig.prune.mapserverindex=\u00cdndice de mapa del servidor
 dialog.saveconfig.prune.mapserverurl=Direcci\u00f3n URL de mapa del servidor
+dialog.saveconfig.prune.mapsourcelist=Fuentes de cartas
+dialog.saveconfig.prune.diskcache=Directorio de cartas
 dialog.saveconfig.prune.kmzimagewidth=Ancho de im\u00e1genes en kmz
 dialog.saveconfig.prune.kmzimageheight=Alto de im\u00e1genes en kmz
 dialog.saveconfig.prune.colourscheme=Color de esquema
 dialog.saveconfig.prune.kmzimagewidth=Ancho de im\u00e1genes en kmz
 dialog.saveconfig.prune.kmzimageheight=Alto de im\u00e1genes en kmz
 dialog.saveconfig.prune.colourscheme=Color de esquema
@@ -362,6 +363,9 @@ dialog.setlanguage.secondintro=Usted necesita salvar su configuraci\u00f3n y lue
 dialog.setlanguage.language=Lenguaje
 dialog.setlanguage.languagefile=Archivo de lenguaje
 dialog.setlanguage.endmessage=Ahora salve su configuraci\u00f3n y reinicie Prune\npara que los cambios tomen efecto.
 dialog.setlanguage.language=Lenguaje
 dialog.setlanguage.languagefile=Archivo de lenguaje
 dialog.setlanguage.endmessage=Ahora salve su configuraci\u00f3n y reinicie Prune\npara que los cambios tomen efecto.
+dialog.diskcache.save=Cargar cartas
+dialog.diskcache.dir=Directorio de cartas
+dialog.diskcache.createdir=Crear directorio
 
 # 3d window
 dialog.3d.title=Prune vista 3-D
 
 # 3d window
 dialog.3d.title=Prune vista 3-D
@@ -423,6 +427,7 @@ button.guessfields=Adivinar campos
 button.showwebpage=Mostrar p\u00e1gina web
 button.check=Verificar
 button.resettodefaults=Restablecer valores a los predeterminados
 button.showwebpage=Mostrar p\u00e1gina web
 button.check=Verificar
 button.resettodefaults=Restablecer valores a los predeterminados
+button.delete=Eliminar
 
 # File types
 filetype.txt=Archivos TXT
 
 # File types
 filetype.txt=Archivos TXT
@@ -437,6 +442,7 @@ filetype.svg=Archivos SVG
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Ning\u00fan dato cargado
 display.noaltitudes=Los datos del track no incluyen altitudes
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Ning\u00fan dato cargado
 display.noaltitudes=Los datos del track no incluyen altitudes
+display.notimestamps=Los datos del track no incluyen tiempos
 details.trackdetails=Detalles del track
 details.notrack=Ning\u00fan track cargado
 details.track.points=Puntos
 details.trackdetails=Detalles del track
 details.notrack=Ning\u00fan track cargado
 details.track.points=Puntos
@@ -462,6 +468,7 @@ display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=Velocidad media
 details.range.avemovingspeed=Moviendo promedio
 display.range.time.days=d
 details.range.avespeed=Velocidad media
 details.range.avemovingspeed=Moviendo promedio
+details.range.maxspeed=Velocidad m\u00e1xima
 details.range.numsegments=N\u00famero de segmentos
 details.range.gradient=Gradiente
 details.waypointsphotos.waypoints=Waypoints
 details.range.numsegments=N\u00famero de segmentos
 details.range.gradient=Gradiente
 details.waypointsphotos.waypoints=Waypoints
@@ -534,8 +541,8 @@ undo.rearrangewaypoints=reordenar waypoints
 undo.connectphoto=conectar foto
 undo.disconnectphoto=desconectar foto
 undo.correlate=correlacionar fotos
 undo.connectphoto=conectar foto
 undo.disconnectphoto=desconectar foto
 undo.correlate=correlacionar fotos
-undo.rotatephoto=girar foto
 undo.createpoint=crear punto
 undo.createpoint=crear punto
+undo.rotatephoto=girar foto
 
 # Error messages
 error.save.dialogtitle=Fallo al guardar datos
 
 # Error messages
 error.save.dialogtitle=Fallo al guardar datos
index b5d9e276e1e499f51bb81c2b21e62315b888f1f8..dcbc3a7c65a6172c946f23026d24d0036e840895 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=Fichier
 
 # Menu entries
 menu.file=Fichier
-menu.file.open=Ouvrir fichier
 menu.file.addphotos=Ajouter photos
 menu.file.save=Enregistrer
 menu.file.exit=Quitter
 menu.file.addphotos=Ajouter photos
 menu.file.save=Enregistrer
 menu.file.exit=Quitter
-menu.edit=\u00c9dition
 menu.track=Trace
 menu.track=Trace
-menu.edit.undo=Annuler
-menu.edit.clearundo=Purger la liste d'annulation
-menu.edit.editpoint=Editer le point
-menu.edit.deletepoint=Supprimer le point
-menu.edit.deleterange=Supprimer l'\u00e9tendue
-menu.edit.deletemarked=Supprimer les points marqu\u00e9s
-menu.edit.interpolate=Interpoler
-menu.edit.average=Cr\u00e9er un point pour la s\u00e9lection
-menu.edit.reverse=Inverser l'\u00e9tendue
-menu.edit.mergetracksegments=Fusionner les segments de trace
-menu.edit.rearrange=R\u00e9arranger les waypoints
-menu.edit.rearrange.start=Tous au d\u00e9but du fichier
-menu.edit.rearrange.end=Tous \u00e0 la fin du fichier
-menu.edit.rearrange.nearest=Chacun au point de trace le plus proche
-menu.edit.cutandmove=Couper et bouger la s\u00e9lection
-menu.select=S\u00e9lectionner
+menu.track.undo=Annuler
+menu.track.clearundo=Purger la liste d'annulation
+menu.track.deletemarked=Supprimer les points marqu\u00e9s
+menu.track.rearrange=R\u00e9arranger les waypoints
+menu.track.rearrange.start=Tous au d\u00e9but du fichier
+menu.track.rearrange.end=Tous \u00e0 la fin du fichier
+menu.track.rearrange.nearest=Chacun au point de trace le plus proche
 menu.range=\u00c9tendue
 menu.range=\u00c9tendue
+menu.range.all=Tout s\u00e9lectionner
+menu.range.none=Rien s\u00e9lectionner
+menu.range.start=D\u00e9finir le d\u00e9but de l'\u00e9tendue
+menu.range.end=D\u00e9finir la fin de l'\u00e9tendue
+menu.range.deleterange=Supprimer l'\u00e9tendue
+menu.range.interpolate=Interpoler
+menu.range.average=Cr\u00e9er un point pour la s\u00e9lection
+menu.range.reverse=Inverser l'\u00e9tendue
+menu.range.mergetracksegments=Fusionner les segments de trace
+menu.range.cutandmove=Couper et bouger la s\u00e9lection
 menu.point=Point
 menu.point=Point
-menu.select.all=Tout s\u00e9lectionner
-menu.select.none=Rien s\u00e9lectionner
-menu.select.start=D\u00e9finir le d\u00e9but de l'\u00e9tendue
-menu.select.end=D\u00e9finir la fin de l'\u00e9tendue
+menu.point.editpoint=Editer le point
+menu.point.deletepoint=Supprimer le point
 menu.photo=Photo
 menu.photo.saveexif=Enregistrer dans les Exif
 menu.photo.connect=Relier au point
 menu.photo=Photo
 menu.photo.saveexif=Enregistrer dans les Exif
 menu.photo.connect=Relier au point
@@ -44,7 +41,7 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Cartes dans Bing
 menu.settings=Pr\u00e9f\u00e9rences
 menu.view.browser.yahoo=Yahoo maps
 menu.view.browser.bing=Cartes dans Bing
 menu.settings=Pr\u00e9f\u00e9rences
-menu.settings.showpace=Montrer allure dans les d\u00e9tails
+menu.settings.onlinemode=Charger une carte depuis internet
 menu.help=Aide
 # Popup menu for map
 menu.map.zoomin=Zoom avant
 menu.help=Aide
 # Popup menu for map
 menu.map.zoomin=Zoom avant
@@ -58,8 +55,6 @@ menu.map.showscalebar=Montrer l'echelle
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
-altkey.menu.edit=E
-altkey.menu.select=S
 altkey.menu.track=T
 altkey.menu.range=E
 altkey.menu.point=P
 altkey.menu.track=T
 altkey.menu.range=E
 altkey.menu.point=P
@@ -72,14 +67,15 @@ altkey.menu.help=I
 shortcut.menu.file.open=O
 shortcut.menu.file.load=T
 shortcut.menu.file.save=E
 shortcut.menu.file.open=O
 shortcut.menu.file.load=T
 shortcut.menu.file.save=E
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=S
+shortcut.menu.range.all=S
 shortcut.menu.help.help=A
 
 # Functions
 shortcut.menu.help.help=A
 
 # Functions
-function.loadfromgps=T\u00e9l\u00e9charger du GPS
-function.sendtogps=Envoyer au GPS
+function.open=Ouvrir fichier
+function.loadfromgps=T\u00e9l\u00e9charger donn\u00e9es du GPS
+function.sendtogps=Envoyer donn\u00e9es au GPS
 function.exportkml=Exporter en KML
 function.exportgpx=Exporter en GPX
 function.exportpov=Exporter en POV
 function.exportkml=Exporter en KML
 function.exportgpx=Exporter en GPX
 function.exportpov=Exporter en POV
@@ -98,6 +94,7 @@ function.setmapbg=D\u00e9finir le fond de carte
 function.setkmzimagesize=D\u00e9finir la taille de l'image KMZ
 function.setpaths=D\u00e9finir les chemins des programmes
 function.getgpsies=R\u00e9cup\u00e9rer les traces Gpsies
 function.setkmzimagesize=D\u00e9finir la taille de l'image KMZ
 function.setpaths=D\u00e9finir les chemins des programmes
 function.getgpsies=R\u00e9cup\u00e9rer les traces Gpsies
+function.lookupsrtm=R\u00e9cup\u00e9rer les altitudes depuis SRTM
 function.duplicatepoint=Duppliquer le point
 function.setcolours=R\u00e9gler les couleurs
 function.setlanguage=R\u00e9gler la langue
 function.duplicatepoint=Duppliquer le point
 function.setcolours=R\u00e9gler les couleurs
 function.setlanguage=R\u00e9gler la langue
@@ -111,6 +108,7 @@ function.showkeys=Montrer les raccourcis clavier
 function.about=À propos de Prune
 function.checkversion=Chercher une mise \u00e0 jour
 function.saveconfig=Enregistrer les pr\u00e9f\u00e9rences
 function.about=À propos de Prune
 function.checkversion=Chercher une mise \u00e0 jour
 function.saveconfig=Enregistrer les pr\u00e9f\u00e9rences
+function.diskcache=Enregistrer les cartes sur le disque
 
 # Dialogs
 dialog.exit.confirm.title=Quitter Prune
 
 # Dialogs
 dialog.exit.confirm.title=Quitter Prune
@@ -121,12 +119,12 @@ dialog.deletepoint.title=Effacer le point
 dialog.deletepoint.deletephoto=Effacer la photo attach\u00e9e \u00e0 ce point ?
 dialog.deletephoto.title=Effacer la photo
 dialog.deletephoto.deletepoint=Effacer le point attach\u00e9 \u00e0 cette photo ?
 dialog.deletepoint.deletephoto=Effacer la photo attach\u00e9e \u00e0 ce point ?
 dialog.deletephoto.title=Effacer la photo
 dialog.deletephoto.deletepoint=Effacer le point attach\u00e9 \u00e0 cette photo ?
-dialog.openoptions.title=Ouvrir options
-dialog.openoptions.filesnippet=Extrait de fichier
+dialog.openoptions.title=Options d'ouverture
+dialog.openoptions.filesnippet=Extraire vers le fichier
 dialog.load.table.field=Champ
 dialog.load.table.datatype=Type de donn\u00e9e
 dialog.load.table.description=Description
 dialog.load.table.field=Champ
 dialog.load.table.datatype=Type de donn\u00e9e
 dialog.load.table.description=Description
-dialog.delimiter.label=S\u00e9parateur de texte
+dialog.delimiter.label=S\u00e9parateur de champ
 dialog.delimiter.comma=Virgule ,
 dialog.delimiter.tab=Tabulation
 dialog.delimiter.space=Espace
 dialog.delimiter.comma=Virgule ,
 dialog.delimiter.tab=Tabulation
 dialog.delimiter.space=Espace
@@ -138,7 +136,7 @@ dialog.openoptions.deliminfo.norecords=Pas d'enregistrements
 dialog.openoptions.altitudeunits=Unit\u00e9s d'altitude
 dialog.jpegload.subdirectories=Inclure les sous-dossiers
 dialog.jpegload.loadjpegswithoutcoords=Inclure les photos sans coordonn\u00e9es
 dialog.openoptions.altitudeunits=Unit\u00e9s d'altitude
 dialog.jpegload.subdirectories=Inclure les sous-dossiers
 dialog.jpegload.loadjpegswithoutcoords=Inclure les photos sans coordonn\u00e9es
-dialog.jpegload.loadjpegsoutsidearea=Inclure des photos en dehors de l'endroit actuel
+dialog.jpegload.loadjpegsoutsidearea=Inclure des photos en dehors de la zone actuel
 dialog.jpegload.progress.title=Chargement des photos
 dialog.jpegload.progress=Veuillez patienter pendant la recherche des photos
 dialog.gpsload.nogpsbabel=Gpsbabel introuvable. Continuer ?
 dialog.jpegload.progress.title=Chargement des photos
 dialog.jpegload.progress=Veuillez patienter pendant la recherche des photos
 dialog.gpsload.nogpsbabel=Gpsbabel introuvable. Continuer ?
@@ -153,9 +151,9 @@ dialog.gpssend.trackname=Nom de trace
 dialog.saveoptions.title=Enregistrer le fichier
 dialog.save.fieldstosave=Champs \u00e0 enregistrer
 dialog.save.table.field=Champ
 dialog.saveoptions.title=Enregistrer le fichier
 dialog.save.fieldstosave=Champs \u00e0 enregistrer
 dialog.save.table.field=Champ
-dialog.save.table.hasdata=Poss\u00e8de une information
+dialog.save.table.hasdata=Contient une donn\u00e9e
 dialog.save.table.save=Enregistrer
 dialog.save.table.save=Enregistrer
-dialog.save.headerrow=Ent\u00eates
+dialog.save.headerrow=En-t\u00eates
 dialog.save.coordinateunits=Unit\u00e9s des coordonn\u00e9es
 dialog.save.altitudeunits=Unit\u00e9s d'altitude
 dialog.save.timestampformat=Format de l'heure
 dialog.save.coordinateunits=Unit\u00e9s des coordonn\u00e9es
 dialog.save.altitudeunits=Unit\u00e9s d'altitude
 dialog.save.timestampformat=Format de l'heure
@@ -163,14 +161,14 @@ dialog.save.overwrite.title=Le fichier existe d\u00e9j\u00e0
 dialog.save.overwrite.text=Ce fichier existe d\u00e9j\u00e0. \u00cates-vous s\u00fbr de vouloir \u00e9craser ce fichier ?
 dialog.save.notypesselected=Aucun type de point n\u2019a \u00e9t\u00e9 s\u00e9lectionn\u00e9
 dialog.exportkml.text=Titre pour les donn\u00e9es
 dialog.save.overwrite.text=Ce fichier existe d\u00e9j\u00e0. \u00cates-vous s\u00fbr de vouloir \u00e9craser ce fichier ?
 dialog.save.notypesselected=Aucun type de point n\u2019a \u00e9t\u00e9 s\u00e9lectionn\u00e9
 dialog.exportkml.text=Titre pour les donn\u00e9es
-dialog.exportkml.altitude=Absolues altitudes (pour aviation)
+dialog.exportkml.altitude=Altitudes absolues (pour l'aviation)
 dialog.exportkml.kmz=Compresser au format kmz
 dialog.exportkml.exportimages=Exporter les vignettes au format kmz
 dialog.exportkml.trackcolour=Couleur de la trace
 dialog.exportgpx.name=Nom
 dialog.exportgpx.desc=L\u00e9gende
 dialog.exportgpx.includetimestamps=Inclure l'heure pour chaque point
 dialog.exportkml.kmz=Compresser au format kmz
 dialog.exportkml.exportimages=Exporter les vignettes au format kmz
 dialog.exportkml.trackcolour=Couleur de la trace
 dialog.exportgpx.name=Nom
 dialog.exportgpx.desc=L\u00e9gende
 dialog.exportgpx.includetimestamps=Inclure l'heure pour chaque point
-dialog.exportgpx.copysource=Copier le XML source
+dialog.exportgpx.copysource=Copier la source xml
 dialog.exportpov.text=Entrez les param\u00e8tres pour l'export POV
 dialog.exportpov.font=Police
 dialog.exportpov.camerax=Cam\u00e9ra X
 dialog.exportpov.text=Entrez les param\u00e8tres pour l'export POV
 dialog.exportpov.font=Police
 dialog.exportpov.camerax=Cam\u00e9ra X
@@ -216,8 +214,6 @@ dialog.addtimeoffset.minutes=Minutes
 dialog.addtimeoffset.notimestamps=Ne peut pas d\u00e9caler l'heure; cette s\u00e9lection ne contient pas de donn\u00e9es d'heure
 dialog.findwaypoint.intro=Entrez une partie du nom de waypoint
 dialog.findwaypoint.search=Chercher
 dialog.addtimeoffset.notimestamps=Ne peut pas d\u00e9caler l'heure; cette s\u00e9lection ne contient pas de donn\u00e9es d'heure
 dialog.findwaypoint.intro=Entrez une partie du nom de waypoint
 dialog.findwaypoint.search=Chercher
-dialog.connect.title=Lier la photo au point
-dialog.connectphoto.clonepoint=Ce point est d\u00e9j\u00e0 li\u00e9 \u00e0 une photo.\nVoulez-vous faire une copie de ce point ?
 dialog.saveexif.title=Enregistrer Exif
 dialog.saveexif.intro=S\u00e9lectionner les photos \u00e0 sauver \u00e0 l'aide des cases \u00e0 cocher
 dialog.saveexif.nothingtosave=Coordonn\u00e9es inchang\u00e9es, rien \u00e0 enregistrer
 dialog.saveexif.title=Enregistrer Exif
 dialog.saveexif.intro=S\u00e9lectionner les photos \u00e0 sauver \u00e0 l'aide des cases \u00e0 cocher
 dialog.saveexif.nothingtosave=Coordonn\u00e9es inchang\u00e9es, rien \u00e0 enregistrer
@@ -245,11 +241,14 @@ dialog.distances.column.to=Vers le point
 dialog.distances.currentpoint=Point courant
 dialog.distances.toofewpoints=Cette fonction a besoin de waypoints pour calculer les distances entre eux
 dialog.fullrangedetails.intro=Voici les d\u00e9tails pour l\u2019\u00e9tendue s\u00e9lectionn\u00e9e
 dialog.distances.currentpoint=Point courant
 dialog.distances.toofewpoints=Cette fonction a besoin de waypoints pour calculer les distances entre eux
 dialog.fullrangedetails.intro=Voici les d\u00e9tails pour l\u2019\u00e9tendue s\u00e9lectionn\u00e9e
-dialog.setmapbg.mapnik=Mapnik (d\u00e9faut)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=Autres
-dialog.setmapbg.server=URL du serveur
+dialog.setmapbg.intro=S\u00e9lectionnez une source de cartes, ou ajoutez-en une nouvelle
+dialog.addmapsource.title=Ajouter une nouvelle source de cartes
+dialog.addmapsource.sourcename=Nom de la source
+dialog.addmapsource.layer1url=URL de la premi\u00e8re couche
+dialog.addmapsource.layer2url=URL optionnelle de la deuxi\u00e8me couche
+dialog.addmapsource.maxzoom=Niveau de zoom maximum
+dialog.addmapsource.cloudstyle=Taille
+dialog.addmapsource.noname=Sans-titre
 dialog.gpsies.column.name=Nom de trace
 dialog.gpsies.column.length=Distance
 dialog.gpsies.description=Description
 dialog.gpsies.column.name=Nom de trace
 dialog.gpsies.column.length=Distance
 dialog.gpsies.description=Description
@@ -300,9 +299,9 @@ dialog.about.version=Version
 dialog.about.build=Build
 dialog.about.summarytext1=Prune est un programme pour charger, afficher et \u00e9diter des donn\u00e9es de r\u00e9cepteurs GPS.
 dialog.about.summarytext2=Distribu\u00e9 sous license Gnu GPL pour un usage et une am\u00e9lioration libres, ouverts et mondiaux.<br>La copie, la redistribution et la modification sont autoris\u00e9es et encourag\u00e9es<br>selon les conditions d\u00e9taill\u00e9es dans le fichier <code>license.txt</code> inclus.
 dialog.about.build=Build
 dialog.about.summarytext1=Prune est un programme pour charger, afficher et \u00e9diter des donn\u00e9es de r\u00e9cepteurs GPS.
 dialog.about.summarytext2=Distribu\u00e9 sous license Gnu GPL pour un usage et une am\u00e9lioration libres, ouverts et mondiaux.<br>La copie, la redistribution et la modification sont autoris\u00e9es et encourag\u00e9es<br>selon les conditions d\u00e9taill\u00e9es dans le fichier <code>license.txt</code> inclus.
-dialog.about.summarytext3=Consultez la page <code style``=``"font-weight:bold">http://activityworkshop.net/</code> pour plus de d\u00e9tails et des manuels utilisateur.
+dialog.about.summarytext3=Consultez la page <code style="font-weight:bold">http://activityworkshop.net/</code> pour plus de d\u00e9tails et des manuels utilisateur.
 dialog.about.languages=Langues disponibles
 dialog.about.languages=Langues disponibles
-dialog.about.translatedby=Texte en fran\u00e7ais par Petrovsk et theYinYeti.
+dialog.about.translatedby=Texte en fran\u00e7ais par Petrovsk, theYinYeti et R\u00e9mi.
 dialog.about.systeminfo=Info Syst\u00e8me
 dialog.about.systeminfo.os=Syst\u00e8me d'exploitation
 dialog.about.systeminfo.java=Java Runtime
 dialog.about.systeminfo=Info Syst\u00e8me
 dialog.about.systeminfo.os=Syst\u00e8me d'exploitation
 dialog.about.systeminfo.java=Java Runtime
@@ -311,6 +310,11 @@ dialog.about.systeminfo.povray=Povray install\u00e9
 dialog.about.systeminfo.exiftool=Exiftool install\u00e9
 dialog.about.systeminfo.gpsbabel=Gpsbabel install\u00e9
 dialog.about.systeminfo.gnuplot=Gnuplot install\u00e9
 dialog.about.systeminfo.exiftool=Exiftool install\u00e9
 dialog.about.systeminfo.gpsbabel=Gpsbabel install\u00e9
 dialog.about.systeminfo.gnuplot=Gnuplot install\u00e9
+dialog.about.systeminfo.exiflib=Librairie Exif
+dialog.about.systeminfo.exiflib.internal=Interne
+dialog.about.systeminfo.exiflib.internal.failed=Interne (non-trouv\u00e9)
+dialog.about.systeminfo.exiflib.external=Externe
+dialog.about.systeminfo.exiflib.external.failed=Externe (non-trouv\u00e9)
 dialog.about.yes=Oui
 dialog.about.no=Non
 dialog.about.credits=Cr\u00e9dits
 dialog.about.yes=Oui
 dialog.about.no=Non
 dialog.about.credits=Cr\u00e9dits
@@ -340,18 +344,21 @@ dialog.saveconfig.prune.languagefile=Fichier de langue
 dialog.saveconfig.prune.gpsdevice=Chemin du p\u00e9riph\u00e9rique GPS
 dialog.saveconfig.prune.gpsformat=Format GPS
 dialog.saveconfig.prune.povrayfont=Police povray
 dialog.saveconfig.prune.gpsdevice=Chemin du p\u00e9riph\u00e9rique GPS
 dialog.saveconfig.prune.gpsformat=Format GPS
 dialog.saveconfig.prune.povrayfont=Police povray
-dialog.saveconfig.prune.metricunits=Utiliser le syst\u00e8me m\u00e9trique?
+dialog.saveconfig.prune.metricunits=Utiliser le syst\u00e8me m\u00e9trique ?
 dialog.saveconfig.prune.gnuplotpath=Chemin gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Chemin gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Chemin exiftool
 dialog.saveconfig.prune.mapserverindex=Index du serveur de carte
 dialog.saveconfig.prune.mapserverurl=URL du serveur de carte
 dialog.saveconfig.prune.gnuplotpath=Chemin gnuplot
 dialog.saveconfig.prune.gpsbabelpath=Chemin gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Chemin exiftool
 dialog.saveconfig.prune.mapserverindex=Index du serveur de carte
 dialog.saveconfig.prune.mapserverurl=URL du serveur de carte
-dialog.saveconfig.prune.showpace=Montrer l'allure
+dialog.saveconfig.prune.mapsource=Carte source s\u00e9lectionn\u00e9e
+dialog.saveconfig.prune.mapsourcelist=Sources de cartes
+dialog.saveconfig.prune.diskcache=Cache de carte
 dialog.saveconfig.prune.kmzimagewidth=Largeur de l'image KMZ
 dialog.saveconfig.prune.kmzimageheight=Hauteur de l'image KMZ
 dialog.saveconfig.prune.colourscheme=Mod\u00e8le de couleurs
 dialog.saveconfig.prune.kmltrackcolour=Couleur de la trace KML
 dialog.setpaths.intro=Si vous le souhaitez, vous pouvez d\u00e9finir les chemins des applications externes:
 dialog.saveconfig.prune.kmzimagewidth=Largeur de l'image KMZ
 dialog.saveconfig.prune.kmzimageheight=Hauteur de l'image KMZ
 dialog.saveconfig.prune.colourscheme=Mod\u00e8le de couleurs
 dialog.saveconfig.prune.kmltrackcolour=Couleur de la trace KML
 dialog.setpaths.intro=Si vous le souhaitez, vous pouvez d\u00e9finir les chemins des applications externes:
+dialog.setpaths.found=Chemin trouv\u00e9 ?
 dialog.addaltitude.noaltitudes=L'\u00e9tendue s\u00e9lectionn\u00e9e de contient pas d'altitudes
 dialog.addaltitude.desc=D\u00e9callage d'altitude \u00e0 ajouter
 dialog.setcolours.intro=Cliquez sur une couleur pour la changer
 dialog.addaltitude.noaltitudes=L'\u00e9tendue s\u00e9lectionn\u00e9e de contient pas d'altitudes
 dialog.addaltitude.desc=D\u00e9callage d'altitude \u00e0 ajouter
 dialog.setcolours.intro=Cliquez sur une couleur pour la changer
@@ -367,8 +374,15 @@ dialog.colourchooser.title=Choisissez la couleur
 dialog.colourchooser.red=Rouge
 dialog.colourchooser.green=Vert
 dialog.colourchooser.blue=Bleu
 dialog.colourchooser.red=Rouge
 dialog.colourchooser.green=Vert
 dialog.colourchooser.blue=Bleu
+dialog.setlanguage.firstintro=Vous pouvez s\u00e9lectionner l'une des langues disponibles,<p> ou bien un fichier de langue \u00e0 utiliser.
+dialog.setlanguage.secondintro=Vous devez sauvegarder vos param\u00e8tres puis<p>red\u00e9marrer Prune pour changer de langue.
 dialog.setlanguage.language=Langue
 dialog.setlanguage.languagefile=Fichier de langue
 dialog.setlanguage.language=Langue
 dialog.setlanguage.languagefile=Fichier de langue
+dialog.setlanguage.endmessage=Enregistrez vos r\u00e9glages et red\u00e9marrez Prune\npour que le changement de langue soit effectif.
+dialog.diskcache.save=Enregistrer les images de carte sur le disque
+dialog.diskcache.dir=R\u00e9pertoire cache
+dialog.diskcache.createdir=Cr\u00e9er r\u00e9pertoire
+dialog.diskcache.nocreate=Le r\u00e9pertoire cache n'est pas cr\u00e9\u00e9
 
 # 3d window
 dialog.3d.title=Vue 3D de Prune
 
 # 3d window
 dialog.3d.title=Vue 3D de Prune
@@ -392,7 +406,7 @@ confirm.rearrangewaypoints=Waypoints r\u00e9arrang\u00e9s
 confirm.rearrangephotos=Photos r\u00e9arrang\u00e9es
 confirm.cutandmove=S\u00e9lection d\u00e9plac\u00e9e
 confirm.convertnamestotimes=Noms de waypoints convertis
 confirm.rearrangephotos=Photos r\u00e9arrang\u00e9es
 confirm.cutandmove=S\u00e9lection d\u00e9plac\u00e9e
 confirm.convertnamestotimes=Noms de waypoints convertis
-confirm.saveexif.ok1=Enregistrement de
+confirm.saveexif.ok1=Enregistr\u00e9
 confirm.saveexif.ok2=fichiers photo
 confirm.undo.single=op\u00e9ration annul\u00e9e
 confirm.undo.multi=op\u00e9rations annul\u00e9es
 confirm.saveexif.ok2=fichiers photo
 confirm.undo.single=op\u00e9ration annul\u00e9e
 confirm.undo.multi=op\u00e9rations annul\u00e9es
@@ -405,6 +419,8 @@ confirm.correlate.multi=photos ont \u00e9t\u00e9 corr\u00e9l\u00e9es
 confirm.createpoint=Point cr\u00e9\u00e9
 confirm.rotatephoto=Photo tourn\u00e9e
 confirm.running=En cours...
 confirm.createpoint=Point cr\u00e9\u00e9
 confirm.rotatephoto=Photo tourn\u00e9e
 confirm.running=En cours...
+confirm.lookupsrtm1=Trouv\u00e9
+confirm.lookupsrtm2=valeurs d'altitude
 
 # Buttons || These are all the texts for buttons
 button.ok=OK
 
 # Buttons || These are all the texts for buttons
 button.ok=OK
@@ -433,6 +449,9 @@ button.guessfields=Deviner les champs
 button.showwebpage=Montrer page web
 button.check=V\u00e9rifier
 button.resettodefaults=Revenir aux valeurs par d\u00e9faut
 button.showwebpage=Montrer page web
 button.check=V\u00e9rifier
 button.resettodefaults=Revenir aux valeurs par d\u00e9faut
+button.browse=Naviguer...
+button.addnew=Ajouter nouveau...
+button.delete=Supprimer
 
 # File types
 filetype.txt=Fichiers TXT
 
 # File types
 filetype.txt=Fichiers TXT
@@ -447,6 +466,7 @@ filetype.svg=Fichiers SVG
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Pas de donn\u00e9es charg\u00e9es
 display.noaltitudes=La trace ne comporte pas d'information d'altitude
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Pas de donn\u00e9es charg\u00e9es
 display.noaltitudes=La trace ne comporte pas d'information d'altitude
+display.notimestamps=La trace ne comporte pas d'information de temps
 details.trackdetails=D\u00e9tails de la trace
 details.notrack=Pas de trace charg\u00e9e
 details.track.points=Points
 details.trackdetails=D\u00e9tails de la trace
 details.notrack=Pas de trace charg\u00e9e
 details.track.points=Points
@@ -472,6 +492,7 @@ display.range.time.hours=h
 display.range.time.days=j
 details.range.avespeed=Vitesse moyenne
 details.range.avemovingspeed=Moyenne continue
 display.range.time.days=j
 details.range.avespeed=Vitesse moyenne
 details.range.avemovingspeed=Moyenne continue
+details.range.maxspeed=Vitesse maximum
 details.range.numsegments=Nombre de segments
 details.range.pace=Allure
 details.range.gradient=Pente
 details.range.numsegments=Nombre de segments
 details.range.pace=Allure
 details.range.gradient=Pente
@@ -552,6 +573,7 @@ undo.rearrangephotos=R\u00e9arranger les photos
 undo.createpoint=ajouter un point
 undo.rotatephoto=Tourner la photo
 undo.convertnamestotimes=Convertir les noms en points
 undo.createpoint=ajouter un point
 undo.rotatephoto=Tourner la photo
 undo.convertnamestotimes=Convertir les noms en points
+undo.lookupsrtm=Rechercher les altitudes depuis SRTM
 
 # Error messages
 error.save.dialogtitle=Erreur \u00e0 l'enregistrement des donn\u00e9es
 
 # Error messages
 error.save.dialogtitle=Erreur \u00e0 l'enregistrement des donn\u00e9es
@@ -575,6 +597,7 @@ error.jpegload.nofilesfound=Aucun fichier trouv\u00e9
 error.jpegload.nojpegsfound=Aucun fichier jpeg trouv\u00e9
 error.jpegload.noexiffound=Aucune information EXIF trouv\u00e9e
 error.jpegload.nogpsfound=Aucune information GPS trouv\u00e9e
 error.jpegload.nojpegsfound=Aucun fichier jpeg trouv\u00e9
 error.jpegload.noexiffound=Aucune information EXIF trouv\u00e9e
 error.jpegload.nogpsfound=Aucune information GPS trouv\u00e9e
+error.jpegload.exifreadfailed=Information EXIF illisible. Aucune information EXIF ne peut \u00eatre lue\nsans une librairie interne ou externe.
 error.gpsload.unknown=Erreur inconnue
 error.undofailed.title=Echec de l'annulation
 error.undofailed.text=Echec de l'op\u00e9ration d'annulation
 error.gpsload.unknown=Erreur inconnue
 error.undofailed.title=Echec de l'annulation
 error.undofailed.text=Echec de l'op\u00e9ration d'annulation
@@ -586,3 +609,6 @@ error.3d=Un probl\u00e8me est survenu avec l'affichage 3D
 error.readme.notfound=Fichier Lisez-moi introuvable
 error.osmimage.dialogtitle=Erreur au chargement des portions de cartes
 error.osmimage.failed=Erreur du chargement des portions de cartes. V\u00e9rifiez votre connexion internet.
 error.readme.notfound=Fichier Lisez-moi introuvable
 error.osmimage.dialogtitle=Erreur au chargement des portions de cartes
 error.osmimage.failed=Erreur du chargement des portions de cartes. V\u00e9rifiez votre connexion internet.
+error.language.wrongfile=Le fichier s\u00e9lectionn\u00e9 n'est pas un fichier de langue pour Prune
+error.convertnamestotimes.nonames=Aucun nom n'a pu \u00eatre converti en horaire
+error.lookupsrtm.none=Aucune valeur d'altitude trouv\u00e9e
index d76fa2e1ae845757c107c8d37cadfef088a484f6..42e2b3762e090c46e6c12726817ee0120b085895 100644 (file)
@@ -3,22 +3,18 @@
 
 # Menu entries
 menu.file=Berkas
 
 # Menu entries
 menu.file=Berkas
-menu.file.open=Buka
 menu.file.addphotos=Muat foto
 menu.file.save=Simpan
 menu.file.exit=Keluar
 menu.file.addphotos=Muat foto
 menu.file.save=Simpan
 menu.file.exit=Keluar
-#menu.edit=Ubah
 menu.track=Track
 menu.track=Track
-menu.edit.undo=Batal
-
-menu.edit.editpoint=Perbaiki titik
-menu.edit.deletepoint=Hapus titik
-menu.edit.deleterange=Hapus jarak
-#menu.select=Pilih
+menu.track.undo=Batal
+menu.point.editpoint=Perbaiki titik
+menu.point.deletepoint=Hapus titik
+menu.range.deleterange=Hapus jarak
 menu.range=Jangkauan
 menu.point=Titik
 menu.range=Jangkauan
 menu.point=Titik
-menu.select.all=Pilih semua
-menu.select.none=Tidak memilih
+menu.range.all=Pilih semua
+menu.range.none=Tidak memilih
 menu.photo=Foto
 menu.photo.saveexif=Simpan ke Exif
 menu.photo.connect=Hubungkan ke titik
 menu.photo=Foto
 menu.photo.saveexif=Simpan ke Exif
 menu.photo.connect=Hubungkan ke titik
@@ -37,8 +33,6 @@ menu.map.showmap=Tampilkan peta
 
 # Alt keys for menus
 altkey.menu.file=B
 
 # Alt keys for menus
 altkey.menu.file=B
-#altkey.menu.edit=U
-#altkey.menu.select=P
 altkey.menu.track=T
 altkey.menu.range=J
 altkey.menu.point=K
 altkey.menu.track=T
 altkey.menu.range=J
 altkey.menu.point=K
@@ -51,12 +45,13 @@ altkey.menu.help=N
 shortcut.menu.file.open=B
 shortcut.menu.file.load=M
 shortcut.menu.file.save=S
 shortcut.menu.file.open=B
 shortcut.menu.file.load=M
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=P
 shortcut.menu.edit.compress=P
-shortcut.menu.select.all=-
+shortcut.menu.range.all=-
 shortcut.menu.help.help=-
 
 # Functions
 shortcut.menu.help.help=-
 
 # Functions
+function.open=Buka
 function.loadfromgps=Muat data dari GPS
 function.sendtogps=Kirim data ke GPS
 function.exportkml=Ekspor KML
 function.loadfromgps=Muat data dari GPS
 function.sendtogps=Kirim data ke GPS
 function.exportkml=Ekspor KML
@@ -64,12 +59,10 @@ function.exportgpx=Ekspor GPX
 function.exportpov=Ekspor POV
 function.editwaypointname=Perbaiki Nama waypoint
 function.compress=Padatkan jalur
 function.exportpov=Ekspor POV
 function.editwaypointname=Perbaiki Nama waypoint
 function.compress=Padatkan jalur
-
 function.findwaypoint=Menemukan waypoint
 function.charts=Grafik
 function.show3d=Lihat tiga-D
 function.distances=Jarak
 function.findwaypoint=Menemukan waypoint
 function.charts=Grafik
 function.show3d=Lihat tiga-D
 function.distances=Jarak
-
 function.correlatephotos=Korelasikan foto
 function.help=Bantuan
 function.about=Tentang Prune
 function.correlatephotos=Korelasikan foto
 function.help=Bantuan
 function.about=Tentang Prune
index 0eb5179b41ddede3c80b116709a179b84dcf6876..0801cafe20b75a63ddd8ff937110b307ca186ad7 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=File
 
 # Menu entries
 menu.file=File
-menu.file.open=Apri file
 menu.file.addphotos=Aggiungi foto
 menu.file.save=Salva
 menu.file.exit=Esci
 menu.file.addphotos=Aggiungi foto
 menu.file.save=Salva
 menu.file.exit=Esci
-menu.edit=Edita
 menu.track=Traccia
 menu.track=Traccia
-menu.edit.undo=Annulla
-menu.edit.clearundo=Cancella lista ultime modifiche
-menu.edit.editpoint=Edita punto
-menu.edit.deletepoint=Cancella punto
-menu.edit.deleterange=Cancella la serie
-menu.edit.deletemarked=Cancella punti marcati
-menu.edit.interpolate=Interpola
-menu.edit.average=Crea punto medio della selezione
-menu.edit.reverse=Inverti la serie
-menu.edit.mergetracksegments=Unisci segmenti traccia
-menu.edit.rearrange=Riorganizza waypoint
-menu.edit.rearrange.start=Tutti all'inizio del file
-menu.edit.rearrange.end=Tutti alla fine del file
-menu.edit.rearrange.nearest=Sul punto pi\u00f9 vicino
-menu.edit.cutandmove=Taglia e muovi la selezione
-menu.select=Seleziona
+menu.track.undo=Annulla
+menu.track.clearundo=Cancella lista ultime modifiche
+menu.point.editpoint=Edita punto
+menu.point.deletepoint=Cancella punto
+menu.range.deleterange=Cancella la serie
+menu.track.deletemarked=Cancella punti marcati
+menu.range.interpolate=Interpola
+menu.range.average=Crea punto medio della selezione
+menu.range.reverse=Inverti la serie
+menu.range.mergetracksegments=Unisci segmenti traccia
+menu.track.rearrange=Riorganizza waypoint
+menu.track.rearrange.start=Tutti all'inizio del file
+menu.track.rearrange.end=Tutti alla fine del file
+menu.track.rearrange.nearest=Sul punto pi\u00f9 vicino
+menu.range.cutandmove=Taglia e muovi la selezione
 menu.range=Serie
 menu.point=Punto
 menu.range=Serie
 menu.point=Punto
-menu.select.all=Seleziona tutto
-menu.select.none=Deseleziona tutto
-menu.select.start=Imposta inizio serie
-menu.select.end=Imposta fine serie
+menu.range.all=Seleziona tutto
+menu.range.none=Deseleziona tutto
+menu.range.start=Imposta inizio serie
+menu.range.end=Imposta fine serie
 menu.photo=Foto
 menu.photo.saveexif=Salva su Exif
 menu.photo.connect=Collega al punto
 menu.photo=Foto
 menu.photo.saveexif=Salva su Exif
 menu.photo.connect=Collega al punto
@@ -44,7 +41,6 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=mappe Yahoo
 menu.view.browser.bing=mappe Bing
 menu.settings=Preferenze
 menu.view.browser.yahoo=mappe Yahoo
 menu.view.browser.bing=mappe Bing
 menu.settings=Preferenze
-menu.settings.showpace=Mostra passo nel display serie
 menu.help=Aiuto
 # Popup menu for map
 menu.map.zoomin=Zoom +
 menu.help=Aiuto
 # Popup menu for map
 menu.map.zoomin=Zoom +
@@ -58,8 +54,6 @@ menu.map.showscalebar=Mostra scala
 
 # Alt keys for menus
 altkey.menu.file=F
 
 # Alt keys for menus
 altkey.menu.file=F
-altkey.menu.edit=E
-altkey.menu.select=S
 altkey.menu.track=T
 altkey.menu.range=S
 altkey.menu.point=P
 altkey.menu.track=T
 altkey.menu.range=S
 altkey.menu.point=P
@@ -72,12 +66,13 @@ altkey.menu.help=A
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=S
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=T
+shortcut.menu.range.all=T
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=Apri file
 function.loadfromgps=Carica dati da GPS
 function.sendtogps=Invia dati al GPS
 function.exportkml=Esporta in KML
 function.loadfromgps=Carica dati da GPS
 function.sendtogps=Invia dati al GPS
 function.exportkml=Esporta in KML
@@ -201,8 +196,6 @@ dialog.addtimeoffset.minutes=Minuti
 dialog.addtimeoffset.notimestamps=Non posso aggiungere uno scarto temporale a questa selezione perch\u00e9 non contiene informazioni temporali
 dialog.findwaypoint.intro=Inserisci parte del nome del waypoint
 dialog.findwaypoint.search=Cerca
 dialog.addtimeoffset.notimestamps=Non posso aggiungere uno scarto temporale a questa selezione perch\u00e9 non contiene informazioni temporali
 dialog.findwaypoint.intro=Inserisci parte del nome del waypoint
 dialog.findwaypoint.search=Cerca
-dialog.connect.title=Collega la foto al punto
-dialog.connectphoto.clonepoint=Questo punto ha gi\u00e0 una foto collegata.\nVuoi fare una copia del punto?
 dialog.saveexif.title=Salva Exif
 dialog.saveexif.intro=Seleziona le foto da salvare usando le caselle di spunta
 dialog.saveexif.nothingtosave=Le coordinate non sono cambiate, niente da registrare
 dialog.saveexif.title=Salva Exif
 dialog.saveexif.intro=Seleziona le foto da salvare usando le caselle di spunta
 dialog.saveexif.nothingtosave=Le coordinate non sono cambiate, niente da registrare
@@ -318,7 +311,6 @@ dialog.saveconfig.prune.gpsbabelpath=Path gpsbabel
 dialog.saveconfig.prune.exiftoolpath=Path exiftool
 dialog.saveconfig.prune.mapserverindex=Indice server mappe
 dialog.saveconfig.prune.mapserverurl=URL del server mappe
 dialog.saveconfig.prune.exiftoolpath=Path exiftool
 dialog.saveconfig.prune.mapserverindex=Indice server mappe
 dialog.saveconfig.prune.mapserverurl=URL del server mappe
-dialog.saveconfig.prune.showpace=Mostra passo
 dialog.saveconfig.prune.kmzimagewidth=larghezza immagine KMZ
 dialog.saveconfig.prune.kmzimageheight=altezza immagine KMZ
 dialog.setpaths.intro=Se necessario, puoi indicare il percorso delle applicazioni esterne:
 dialog.saveconfig.prune.kmzimagewidth=larghezza immagine KMZ
 dialog.saveconfig.prune.kmzimageheight=altezza immagine KMZ
 dialog.setpaths.intro=Se necessario, puoi indicare il percorso delle applicazioni esterne:
index a54fa2ef9046cd9ea35b3b0d36167e38aea34083..ee54e3dbd2aa592d6e9f49494b530790905be842 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=\u30d5\u30a1\u30a4\u30eb
 
 # Menu entries
 menu.file=\u30d5\u30a1\u30a4\u30eb
-menu.file.open=\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f
 menu.file.addphotos=\u5199\u771f\u3092\u8ffd\u52a0
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u7d42\u4e86
 menu.file.addphotos=\u5199\u771f\u3092\u8ffd\u52a0
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u7d42\u4e86
-menu.edit=\u7de8\u96c6
 menu.track=\u30c8\u30e9\u30c3\u30af
 menu.track=\u30c8\u30e9\u30c3\u30af
-menu.edit.undo=\u30a2\u30f3\u30c9\u30a5
-menu.edit.clearundo=\u30a2\u30f3\u30c9\u30a5\u30ea\u30b9\u30c8\u3092\u7a7a\u306b\u3059\u308b
-menu.edit.editpoint=\u70b9\u3092\u7de8\u96c6
-menu.edit.deletepoint=\u70b9\u3092\u524a\u9664
-menu.edit.deleterange=\u7bc4\u56f2\u3092\u524a\u9664
-menu.edit.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664
-menu.edit.interpolate=\u88dc\u5b8c
-menu.edit.average=\u9078\u629e\u7bc4\u56f2\u3092\u5e73\u5747\u5316
-menu.edit.reverse=\u7bc4\u56f2\u3092\u53cd\u8ee2
-menu.edit.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u3092\u7d71\u5408
-menu.edit.rearrange=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u4e26\u3079\u66ff\u3048
-menu.edit.rearrange.start=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u59cb\u70b9\u306b
-menu.edit.rearrange.end=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u7d42\u70b9\u306b
-menu.edit.rearrange.nearest=\u305d\u308c\u305e\u308c\u3092\u6700\u8fd1\u306e\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b
-menu.edit.cutandmove=\u9078\u629e\u7bc4\u56f2\u3092\u79fb\u52d5
-menu.select=\u9078\u629e
+menu.track.undo=\u30a2\u30f3\u30c9\u30a5
+menu.track.clearundo=\u30a2\u30f3\u30c9\u30a5\u30ea\u30b9\u30c8\u3092\u7a7a\u306b\u3059\u308b
+menu.point.editpoint=\u70b9\u3092\u7de8\u96c6
+menu.point.deletepoint=\u70b9\u3092\u524a\u9664
+menu.range.deleterange=\u7bc4\u56f2\u3092\u524a\u9664
+menu.track.deletemarked=\u5370\u306e\u4ed8\u3044\u305f\u70b9\u3092\u524a\u9664
+menu.range.interpolate=\u88dc\u5b8c
+menu.range.average=\u9078\u629e\u7bc4\u56f2\u3092\u5e73\u5747\u5316
+menu.range.reverse=\u7bc4\u56f2\u3092\u53cd\u8ee2
+menu.range.mergetracksegments=\u30c8\u30e9\u30c3\u30af\u30bb\u30b0\u30e1\u30f3\u30c8\u3092\u7d71\u5408
+menu.track.rearrange=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u4e26\u3079\u66ff\u3048
+menu.track.rearrange.start=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u59cb\u70b9\u306b
+menu.track.rearrange.end=\u5168\u3066\u3092\u30d5\u30a1\u30a4\u30eb\u306e\u7d42\u70b9\u306b
+menu.track.rearrange.nearest=\u305d\u308c\u305e\u308c\u3092\u6700\u8fd1\u306e\u30c8\u30e9\u30c3\u30af\u30dd\u30a4\u30f3\u30c8\u306b
+menu.range.cutandmove=\u9078\u629e\u7bc4\u56f2\u3092\u79fb\u52d5
 menu.range=\u7bc4\u56f2
 menu.point=\u70b9
 menu.range=\u7bc4\u56f2
 menu.point=\u70b9
-menu.select.all=\u5168\u3066\u9078\u629e
-menu.select.none=\u9078\u629e\u89e3\u9664
-menu.select.start=\u958b\u59cb\u70b9\u3092\u7f6e\u304f
-menu.select.end=\u7d42\u4e86\u70b9\u3092\u7f6e\u304f
+menu.range.all=\u5168\u3066\u9078\u629e
+menu.range.none=\u9078\u629e\u89e3\u9664
+menu.range.start=\u958b\u59cb\u70b9\u3092\u7f6e\u304f
+menu.range.end=\u7d42\u4e86\u70b9\u3092\u7f6e\u304f
 menu.photo=\u5199\u771f
 menu.photo.saveexif=Exif\u306b\u4fdd\u5b58
 menu.photo.connect=\u70b9\u306b\u63a5\u7d9a
 menu.photo=\u5199\u771f
 menu.photo.saveexif=Exif\u306b\u4fdd\u5b58
 menu.photo.connect=\u70b9\u306b\u63a5\u7d9a
@@ -44,7 +41,6 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo \u5730\u56f3
 menu.view.browser.bing=Bing \u5730\u56f3
 menu.settings=\u8a2d\u5b9a
 menu.view.browser.yahoo=Yahoo \u5730\u56f3
 menu.view.browser.bing=Bing \u5730\u56f3
 menu.settings=\u8a2d\u5b9a
-menu.settings.showpace=\u8868\u793a\u7bc4\u56f2\u306e\u901f\u5ea6\u3092\u8868\u793a
 menu.help=\u30d8\u30eb\u30d7
 # Popup menu for map
 menu.map.zoomin=\u62e1\u5927
 menu.help=\u30d8\u30eb\u30d7
 # Popup menu for map
 menu.map.zoomin=\u62e1\u5927
@@ -57,6 +53,7 @@ menu.map.showmap=\u5730\u56f3\u3092\u8868\u793a
 menu.map.showscalebar=\u7e2e\u5c3a\u8868\u793a
 
 # Functions
 menu.map.showscalebar=\u7e2e\u5c3a\u8868\u793a
 
 # Functions
+function.open=\u30d5\u30a1\u30a4\u30eb\u3092\u958b\u304f
 function.loadfromgps=GPS\u304b\u3089\u30c7\u30fc\u30bf\u3092\u8aad\u3080
 function.sendtogps=GPS\u3078\u4fdd\u5b58
 function.exportkml=KML\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
 function.loadfromgps=GPS\u304b\u3089\u30c7\u30fc\u30bf\u3092\u8aad\u3080
 function.sendtogps=GPS\u3078\u4fdd\u5b58
 function.exportkml=KML\u306b\u30a8\u30af\u30b9\u30dd\u30fc\u30c8
@@ -195,8 +192,6 @@ dialog.addtimeoffset.minutes=\u5206
 dialog.addtimeoffset.notimestamps=\u3053\u306e\u9078\u629e\u7bc4\u56f2\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u6301\u3063\u3066\u306a\u3044\u306e\u3067\u3001\u504f\u4f4d\u3092\u8db3\u305b\u307e\u305b\u3093\u3002
 dialog.findwaypoint.intro=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d\u306e\u4e00\u90e8\u3092\u5165\u529b
 dialog.findwaypoint.search=\u691c\u7d22
 dialog.addtimeoffset.notimestamps=\u3053\u306e\u9078\u629e\u7bc4\u56f2\u306f\u30bf\u30a4\u30e0\u30b9\u30bf\u30f3\u30d7\u3092\u6301\u3063\u3066\u306a\u3044\u306e\u3067\u3001\u504f\u4f4d\u3092\u8db3\u305b\u307e\u305b\u3093\u3002
 dialog.findwaypoint.intro=\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u540d\u306e\u4e00\u90e8\u3092\u5165\u529b
 dialog.findwaypoint.search=\u691c\u7d22
-dialog.connect.title=\u70b9\u306b\u5199\u771f\u3092\u63a5\u7d9a
-dialog.connectphoto.clonepoint=\u3053\u306e\u70b9\u306f\u65e2\u306b\u5199\u771f\u3092\u6301\u3063\u3066\u307e\u3059\u3002\n\u30a6\u30a7\u30a4\u30dd\u30a4\u30f3\u30c8\u3092\u30b3\u30d4\u30fc\u3057\u307e\u3059\u304b\uff1f
 dialog.saveexif.title=EXIF\u3092\u4fdd\u5b58
 dialog.saveexif.intro=\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3092\u4f7f\u3063\u3066\u3001\u4fdd\u5b58\u3059\u308b\u5199\u771f\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.saveexif.nothingtosave=\u5ea7\u6a19\u60c5\u5831\u306f\u7121\u5909\u66f4\u3067\u3059\u3002\u4fdd\u5b58\u3059\u308b\u3082\u306e\u306f\u3042\u308a\u307e\u305b\u3093\u3002
 dialog.saveexif.title=EXIF\u3092\u4fdd\u5b58
 dialog.saveexif.intro=\u30c1\u30a7\u30c3\u30af\u30dc\u30c3\u30af\u30b9\u3092\u4f7f\u3063\u3066\u3001\u4fdd\u5b58\u3059\u308b\u5199\u771f\u3092\u9078\u629e\u3057\u3066\u304f\u3060\u3055\u3044\u3002
 dialog.saveexif.nothingtosave=\u5ea7\u6a19\u60c5\u5831\u306f\u7121\u5909\u66f4\u3067\u3059\u3002\u4fdd\u5b58\u3059\u308b\u3082\u306e\u306f\u3042\u308a\u307e\u305b\u3093\u3002
@@ -325,7 +320,6 @@ dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.exiftoolpath=exiftool\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306e\u7d22\u5f15(1-4)
 dialog.saveconfig.prune.mapserverurl=\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306eURL
 dialog.saveconfig.prune.exiftoolpath=exiftool\u3078\u306e\u30d1\u30b9
 dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306e\u7d22\u5f15(1-4)
 dialog.saveconfig.prune.mapserverurl=\u5730\u56f3\u30b5\u30fc\u30d0\u30fc\u306eURL
-dialog.saveconfig.prune.showpace=\u30da\u30fc\u30b9\u3092\u8868\u793a
 dialog.saveconfig.prune.kmzimagewidth=KML \u753b\u50cf\u5e45
 dialog.saveconfig.prune.kmzimageheight=KML \u753b\u50cf\u9ad8
 dialog.saveconfig.prune.colourscheme=\u8272\u306e\u30b9\u30ad\u30fc\u30e0
 dialog.saveconfig.prune.kmzimagewidth=KML \u753b\u50cf\u5e45
 dialog.saveconfig.prune.kmzimageheight=KML \u753b\u50cf\u9ad8
 dialog.saveconfig.prune.colourscheme=\u8272\u306e\u30b9\u30ad\u30fc\u30e0
index c731f843750ef072cb7b8bdcc8be6bf23e85790a..b0456302544d7f7697776dffa447f5f71a25a1c0 100644 (file)
@@ -3,32 +3,31 @@
 
 # Menu entries
 menu.file=Plik
 
 # Menu entries
 menu.file=Plik
-menu.file.open=Otw\u00f3rz
 menu.file.addphotos=Dodaj zdj\u0119cia
 menu.file.save=Zapisz
 menu.file.exit=Zako\u0144cz
 menu.track=\u015acie\u017cka
 menu.file.addphotos=Dodaj zdj\u0119cia
 menu.file.save=Zapisz
 menu.file.exit=Zako\u0144cz
 menu.track=\u015acie\u017cka
-menu.edit.undo=Cofnij
-menu.edit.clearundo=Wyczy\u015b\u0107 list\u0119 zmian
-menu.edit.editpoint=Edytuj punkt
-menu.edit.deletepoint=Usu\u0144 punkt
-menu.edit.deleterange=Usu\u0144 zakres
-menu.edit.deletemarked=Usu\u0144 zaznaczone punkty
-menu.edit.interpolate=Wstaw pomi\u0119dzy
-menu.edit.average=U\u015brednij zaznaczenie
-menu.edit.reverse=Odwr\u00f3\u0107 zakres
-menu.edit.mergetracksegments=Po\u0142\u0105cz fragmenty \u015bcie\u017cek
-menu.edit.rearrange=Zmie\u0144 kolejno\u015b\u0107 punkt\u00f3w po\u015brednich
-menu.edit.rearrange.start=Wszystkie na pocz\u0105tek \u015bcie\u017cki
-menu.edit.rearrange.end=Wszystkie na koniec \u015bcie\u017cki
-menu.edit.rearrange.nearest=Do najbli\u017cszego punktu
-menu.edit.cutandmove=Wytnij i przesu\u0144 zaznaczenie
+menu.track.undo=Cofnij
+menu.track.clearundo=Wyczy\u015b\u0107 list\u0119 zmian
+menu.track.deletemarked=Usu\u0144 zaznaczone punkty
+menu.track.rearrange=Zmie\u0144 kolejno\u015b\u0107 punkt\u00f3w po\u015brednich
+menu.track.rearrange.start=Wszystkie na pocz\u0105tek \u015bcie\u017cki
+menu.track.rearrange.end=Wszystkie na koniec \u015bcie\u017cki
+menu.track.rearrange.nearest=Do najbli\u017cszego punktu
 menu.range=Zakres
 menu.range=Zakres
+menu.range.all=Zaznacz wszystko
+menu.range.none=Usu\u0144 zaznaczenie
+menu.range.start=Zaznacz pocz\u0105tek zakresu
+menu.range.end=Zaznacz koniec zakresu
+menu.range.deleterange=Usu\u0144 zakres
+menu.range.interpolate=Wstaw pomi\u0119dzy
+menu.range.average=U\u015brednij zaznaczenie
+menu.range.reverse=Odwr\u00f3\u0107 zakres
+menu.range.mergetracksegments=Po\u0142\u0105cz fragmenty \u015bcie\u017cek
+menu.range.cutandmove=Wytnij i przesu\u0144 zaznaczenie
 menu.point=Punkt
 menu.point=Punkt
-menu.select.all=Zaznacz wszystko
-menu.select.none=Usu\u0144 zaznaczenie
-menu.select.start=Zaznacz pocz\u0105tek zakresu
-menu.select.end=Zaznacz koniec zakresu
+menu.point.editpoint=Edytuj punkt
+menu.point.deletepoint=Usu\u0144 punkt
 menu.photo=Zdj\u0119cie
 menu.photo.saveexif=Zapisz Exif
 menu.photo.connect=Przy\u0142\u0105cz do punktu
 menu.photo=Zdj\u0119cie
 menu.photo.saveexif=Zapisz Exif
 menu.photo.connect=Przy\u0142\u0105cz do punktu
@@ -42,6 +41,7 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Mapy Yahoo
 menu.view.browser.bing=Mapy Bing
 menu.settings=Ustawienia
 menu.view.browser.yahoo=Mapy Yahoo
 menu.view.browser.bing=Mapy Bing
 menu.settings=Ustawienia
+menu.settings.onlinemode=\u0141aduj mapy z sieci
 menu.help=Pomoc
 # Popup menu for map
 menu.map.zoomin=Powi\u0119ksz
 menu.help=Pomoc
 # Popup menu for map
 menu.map.zoomin=Powi\u0119ksz
@@ -67,12 +67,13 @@ altkey.menu.help=M
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
 shortcut.menu.file.open=O
 shortcut.menu.file.load=L
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=A
+shortcut.menu.range.all=A
 shortcut.menu.help.help=H
 
 # Functions
 shortcut.menu.help.help=H
 
 # Functions
+function.open=Otw\u00f3rz
 function.loadfromgps=\u0141aduj z GPS
 function.sendtogps=Wy\u015blij dane do urz\u0105dzenia GPS
 function.exportkml=Eksportuj KML
 function.loadfromgps=\u0141aduj z GPS
 function.sendtogps=Wy\u015blij dane do urz\u0105dzenia GPS
 function.exportkml=Eksportuj KML
@@ -93,6 +94,7 @@ function.setmapbg=Wybierz map\u0119 t\u0142a
 function.setkmzimagesize=Ustaw rozmiar zdj\u0119\u0107 w KMZ
 function.setpaths=Ustaw \u015bcie\u017cki do program\u00f3w
 function.getgpsies=Pobierz \u015bcie\u017cki z Gpsies
 function.setkmzimagesize=Ustaw rozmiar zdj\u0119\u0107 w KMZ
 function.setpaths=Ustaw \u015bcie\u017cki do program\u00f3w
 function.getgpsies=Pobierz \u015bcie\u017cki z Gpsies
+function.lookupsrtm=Pobierz wysoko\u015bci z SRTM
 function.duplicatepoint=Duplikuj plik
 function.setcolours=Ustaw kolory
 function.setlanguage=Zmie\u0144 j\u0119zyk
 function.duplicatepoint=Duplikuj plik
 function.setcolours=Ustaw kolory
 function.setlanguage=Zmie\u0144 j\u0119zyk
@@ -106,6 +108,7 @@ function.showkeys=Poka\u017c klawisze skr\u00f3tu
 function.about=O Prune
 function.checkversion=Sprawd\u017a czy jest nowa wersja
 function.saveconfig=Zapisz ustawienia
 function.about=O Prune
 function.checkversion=Sprawd\u017a czy jest nowa wersja
 function.saveconfig=Zapisz ustawienia
+function.diskcache=Zapisz mapy na dysk
 
 # Dialogs
 dialog.exit.confirm.title=Zako\u0144cz Prune
 
 # Dialogs
 dialog.exit.confirm.title=Zako\u0144cz Prune
@@ -118,6 +121,7 @@ dialog.deletephoto.title=Usu\u0144 zdj\u0119cie
 dialog.deletephoto.deletepoint=Usun\u0105\u0107 punkt do\u0142\u0105czony do tego zdj\u0119cia?
 dialog.openoptions.title=Otw\u00f3rz opcje
 dialog.openoptions.filesnippet=Fragment z pliku
 dialog.deletephoto.deletepoint=Usun\u0105\u0107 punkt do\u0142\u0105czony do tego zdj\u0119cia?
 dialog.openoptions.title=Otw\u00f3rz opcje
 dialog.openoptions.filesnippet=Fragment z pliku
+dialog.open.contentsdoubled=Ten plik zawiera dwie kopie ka\u017cdego punktu.\nRaz jako punkt po\u015bredni, a raz jako punkt \u015bcie\u017cki.
 dialog.load.table.field=Pole
 dialog.load.table.datatype=Typ danych
 dialog.load.table.description=Opis
 dialog.load.table.field=Pole
 dialog.load.table.datatype=Typ danych
 dialog.load.table.description=Opis
@@ -238,11 +242,14 @@ dialog.distances.column.to=Do punktu
 dialog.distances.currentpoint=Wybrany punkt
 dialog.distances.toofewpoints=Ta funkcja wymaga przynajmniej dw\u00f3ch punkt\u00f3w po\u015brednich, aby mo\u017cna by\u0142o obliczy\u0107 odleg\u0142o\u015bci
 dialog.fullrangedetails.intro=Szczeg\u00f3\u0142y wybranego zakresu
 dialog.distances.currentpoint=Wybrany punkt
 dialog.distances.toofewpoints=Ta funkcja wymaga przynajmniej dw\u00f3ch punkt\u00f3w po\u015brednich, aby mo\u017cna by\u0142o obliczy\u0107 odleg\u0142o\u015bci
 dialog.fullrangedetails.intro=Szczeg\u00f3\u0142y wybranego zakresu
-dialog.setmapbg.mapnik=Mapnik (domy\u015blny)
-dialog.setmapbg.osma=Osma
-dialog.setmapbg.cyclemap=Cyclemap
-dialog.setmapbg.other=Inne
-dialog.setmapbg.server=Adres URL serwera
+dialog.setmapbg.intro=Wybierz dostawc\u0119 map t\u0142a lub dodaj nowego
+dialog.addmapsource.title=Dodaj dostawc\u0119 map
+dialog.addmapsource.sourcename=Nazwa dostawcy
+dialog.addmapsource.layer1url=URL pierwszej warstwy
+dialog.addmapsource.layer2url=Opcjonalny URL drugiej warstwy
+dialog.addmapsource.maxzoom=Maksymalny poziom zbli\u017cenia
+dialog.addmapsource.cloudstyle=Numer stylu
+dialog.addmapsource.noname=Nienazwane
 dialog.gpsies.column.name=Nazwa \u015bcie\u017cki
 dialog.gpsies.column.length=D\u0142ugo\u015b\u0107
 dialog.gpsies.description=Opis
 dialog.gpsies.column.name=Nazwa \u015bcie\u017cki
 dialog.gpsies.column.length=D\u0142ugo\u015b\u0107
 dialog.gpsies.description=Opis
@@ -304,6 +311,11 @@ dialog.about.systeminfo.povray=Povray zainstalowany
 dialog.about.systeminfo.exiftool=Exiftool zainstalowany
 dialog.about.systeminfo.gpsbabel=Gpsbabel zainstalowany
 dialog.about.systeminfo.gnuplot=Gnuplot zainstalowany
 dialog.about.systeminfo.exiftool=Exiftool zainstalowany
 dialog.about.systeminfo.gpsbabel=Gpsbabel zainstalowany
 dialog.about.systeminfo.gnuplot=Gnuplot zainstalowany
+dialog.about.systeminfo.exiflib=Biblioteka Exif
+dialog.about.systeminfo.exiflib.internal=Wewn\u0119trzny
+dialog.about.systeminfo.exiflib.internal.failed=Wewn\u0119trzny (nie znaleziony)
+dialog.about.systeminfo.exiflib.external=Zewn\u0119trzny
+dialog.about.systeminfo.exiflib.external.failed=Zewn\u0119trzny (nie znaleziony)
 dialog.about.yes=Tak
 dialog.about.no=Nie
 dialog.about.credits=Podzi\u0119kowania
 dialog.about.yes=Tak
 dialog.about.no=Nie
 dialog.about.credits=Podzi\u0119kowania
@@ -339,11 +351,15 @@ dialog.saveconfig.prune.gpsbabelpath=\u015bcie\u017cka do gpsbabel
 dialog.saveconfig.prune.exiftoolpath=\u015bcie\u017cka do exiftool
 dialog.saveconfig.prune.mapserverindex=kolejny numer serwera map
 dialog.saveconfig.prune.mapserverurl=URL serwera map
 dialog.saveconfig.prune.exiftoolpath=\u015bcie\u017cka do exiftool
 dialog.saveconfig.prune.mapserverindex=kolejny numer serwera map
 dialog.saveconfig.prune.mapserverurl=URL serwera map
+dialog.saveconfig.prune.mapsource=Wybrany dostawca map
+dialog.saveconfig.prune.mapsourcelist=Dostawcy map
+dialog.saveconfig.prune.diskcache=Pami\u0119\u0107 podr\u0119czna map
 dialog.saveconfig.prune.kmzimagewidth=szeroko\u015b\u0107 obrazka w KMZ
 dialog.saveconfig.prune.kmzimageheight=wysoko\u015b\u0107 obrazka w KMZ
 dialog.saveconfig.prune.colourscheme=Schemat kolor\u00f3w
 dialog.saveconfig.prune.kmltrackcolour=Kolor \u015bcie\u017cki w pliku KML
 dialog.setpaths.intro=Je\u015bli zachodzi tak potrzeba, mo\u017cesz wybra\u0107 \u015bcie\u017cki do aplikacji zewn\u0119trznych
 dialog.saveconfig.prune.kmzimagewidth=szeroko\u015b\u0107 obrazka w KMZ
 dialog.saveconfig.prune.kmzimageheight=wysoko\u015b\u0107 obrazka w KMZ
 dialog.saveconfig.prune.colourscheme=Schemat kolor\u00f3w
 dialog.saveconfig.prune.kmltrackcolour=Kolor \u015bcie\u017cki w pliku KML
 dialog.setpaths.intro=Je\u015bli zachodzi tak potrzeba, mo\u017cesz wybra\u0107 \u015bcie\u017cki do aplikacji zewn\u0119trznych
+dialog.setpaths.found=Znalezione \u015bcie\u017cki?
 dialog.addaltitude.noaltitudes=Wybrany zakres nie zawiera danych o wysoko\u015bciach
 dialog.addaltitude.desc=Warto\u015b\u0107 przesuni\u0119cia wysoko\u015bci
 dialog.setcolours.intro=Kliknij na kolor by go wybra\u0107
 dialog.addaltitude.noaltitudes=Wybrany zakres nie zawiera danych o wysoko\u015bciach
 dialog.addaltitude.desc=Warto\u015b\u0107 przesuni\u0119cia wysoko\u015bci
 dialog.setcolours.intro=Kliknij na kolor by go wybra\u0107
@@ -364,6 +380,10 @@ dialog.setlanguage.secondintro=B\u0119dziesz musia\u0142 zapisa\u0107 ustawienia
 dialog.setlanguage.language=J\u0119zyk
 dialog.setlanguage.languagefile=Plik t\u0142umaczenia
 dialog.setlanguage.endmessage=Zapisz ustawienia i zrestartuj Prune\n by zmiana j\u0119zyka odnios\u0142a skutek.
 dialog.setlanguage.language=J\u0119zyk
 dialog.setlanguage.languagefile=Plik t\u0142umaczenia
 dialog.setlanguage.endmessage=Zapisz ustawienia i zrestartuj Prune\n by zmiana j\u0119zyka odnios\u0142a skutek.
+dialog.diskcache.save=Zapisz mapy na dysk
+dialog.diskcache.dir=katalog pami\u0119ci podr\u0119cznej
+dialog.diskcache.createdir=stw\u00f3rz katalog
+dialog.diskcache.nocreate=Nie utworzono katalogu pami\u0119ci podr\u0119cznej
 
 # 3d window
 dialog.3d.title=Prune widok tr\u00f3jwymiarowy
 
 # 3d window
 dialog.3d.title=Prune widok tr\u00f3jwymiarowy
@@ -388,7 +408,7 @@ confirm.rearrangephotos=Zmieniono kolejno\u015b\u0107 zdj\u0119\u0107
 confirm.cutandmove=Przesuni\u0119to zaznaczenie
 confirm.convertnamestotimes=Zmieniono nazwy punkt\u00f3w po\u015brednich
 confirm.saveexif.ok1=Zapisano
 confirm.cutandmove=Przesuni\u0119to zaznaczenie
 confirm.convertnamestotimes=Zmieniono nazwy punkt\u00f3w po\u015brednich
 confirm.saveexif.ok1=Zapisano
-confirm.saveexif.ok2=pliki zdj\u0119\u0107
+confirm.saveexif.ok2=plik(\u00f3w) zdj\u0119\u0107
 confirm.undo.single=cofni\u0119to operacj\u0119
 confirm.undo.multi=operacje zosta\u0142y cofni\u0119te
 confirm.jpegload.single=dodano zdj\u0119cie
 confirm.undo.single=cofni\u0119to operacj\u0119
 confirm.undo.multi=operacje zosta\u0142y cofni\u0119te
 confirm.jpegload.single=dodano zdj\u0119cie
@@ -400,6 +420,8 @@ confirm.correlate.multi=zdj\u0119cia zosta\u0142y po\u0142\u0105czone
 confirm.createpoint=stworzono punkt
 confirm.rotatephoto=obr\u00f3cono zdj\u0119cie
 confirm.running=Przetwarzam dane ...
 confirm.createpoint=stworzono punkt
 confirm.rotatephoto=obr\u00f3cono zdj\u0119cie
 confirm.running=Przetwarzam dane ...
+confirm.lookupsrtm1=Znaleziono
+confirm.lookupsrtm2=warto\u015bci wysoko\u015bci
 
 # Buttons || These are all the texts for buttons
 button.ok=OK
 
 # Buttons || These are all the texts for buttons
 button.ok=OK
@@ -429,6 +451,8 @@ button.showwebpage=Poka\u017c stron\u0119 web
 button.check=Sprawd\u017a
 button.resettodefaults=Przywr\u00f3\u0107 domy\u015blne
 button.browse=Przegl\u0105daj...
 button.check=Sprawd\u017a
 button.resettodefaults=Przywr\u00f3\u0107 domy\u015blne
 button.browse=Przegl\u0105daj...
+button.addnew=Dodaj nowy
+button.delete=Usu\u0144
 
 # File types
 filetype.txt=Pliki TXT
 
 # File types
 filetype.txt=Pliki TXT
@@ -443,6 +467,7 @@ filetype.svg=Pliki SVG
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Nie za\u0142adowano danych
 display.noaltitudes=\u015acie\u017cki nie zawieraj\u0105 informacji o wysoko\u015bci
 # Display components || These are all for the side panels showing point/range details
 display.nodata=Nie za\u0142adowano danych
 display.noaltitudes=\u015acie\u017cki nie zawieraj\u0105 informacji o wysoko\u015bci
+display.notimestamps=\u015acie\u017cki nie zawieraj\u0105 informacji o czasie
 details.trackdetails=Szczeg\u00f3\u0142y \u015bcie\u017cki
 details.notrack=Brak za\u0142adowanych \u015bcie\u017cek
 details.track.points=Punkty
 details.trackdetails=Szczeg\u00f3\u0142y \u015bcie\u017cki
 details.notrack=Brak za\u0142adowanych \u015bcie\u017cek
 details.track.points=Punkty
@@ -468,6 +493,7 @@ display.range.time.hours=h
 display.range.time.days=d
 details.range.avespeed=\u015arednia pr\u0119dko\u015b\u0107
 details.range.avemovingspeed=\u015arednie przesuni\u0119cie
 display.range.time.days=d
 details.range.avespeed=\u015arednia pr\u0119dko\u015b\u0107
 details.range.avemovingspeed=\u015arednie przesuni\u0119cie
+details.range.maxspeed=Pr\u0119dko\u015b\u0107 maksymalna
 details.range.numsegments=Liczba segment\u00f3w
 details.range.pace=Tempo
 details.range.gradient=Nachylenie
 details.range.numsegments=Liczba segment\u00f3w
 details.range.pace=Tempo
 details.range.gradient=Nachylenie
@@ -548,6 +574,7 @@ undo.rearrangephotos=zmie\u0144 kolejno\u015b\u0107 zdj\u0119\u0107
 undo.createpoint=stw\u00f3rz punkt
 undo.rotatephoto=obr\u00f3\u0107 zdj\u0119cie
 undo.convertnamestotimes=zamie\u0144 nazwy punkt\u00f3w
 undo.createpoint=stw\u00f3rz punkt
 undo.rotatephoto=obr\u00f3\u0107 zdj\u0119cie
 undo.convertnamestotimes=zamie\u0144 nazwy punkt\u00f3w
+undo.lookupsrtm=szukaj wysoko\u015bci w SRTM
 
 # Error messages
 error.save.dialogtitle=B\u0142\u0105d zapisu danych
 
 # Error messages
 error.save.dialogtitle=B\u0142\u0105d zapisu danych
@@ -571,6 +598,7 @@ error.jpegload.nofilesfound=Nie znaleziono plik\u00f3w
 error.jpegload.nojpegsfound=Nie znaleziono plik\u00f3w jpeg
 error.jpegload.noexiffound=Nie znaleziono informacji EXIF
 error.jpegload.nogpsfound=Nie znaleziono informacji GPS
 error.jpegload.nojpegsfound=Nie znaleziono plik\u00f3w jpeg
 error.jpegload.noexiffound=Nie znaleziono informacji EXIF
 error.jpegload.nogpsfound=Nie znaleziono informacji GPS
+error.jpegload.exifreadfailed=Nie powiod\u0142o si\u0119 odczytanie informacji EXIF\nInformacji tych nie mo\u017cna przeczyta\u0107 bez wewn\u0119trznej lub zewn\u0119trznej biblioteki.
 error.gpsload.unknown=Nieznany b\u0142\u0105d
 error.undofailed.title=Cofnij nie powiod\u0142o si\u0119
 error.undofailed.text=Nie mo\u017cna cofn\u0105\u0107
 error.gpsload.unknown=Nieznany b\u0142\u0105d
 error.undofailed.title=Cofnij nie powiod\u0142o si\u0119
 error.undofailed.text=Nie mo\u017cna cofn\u0105\u0107
@@ -584,3 +612,4 @@ error.osmimage.dialogtitle=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map
 error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map. Sprawd\u017a po\u0142\u0105czenie z internetem.
 error.language.wrongfile=Wybrany plik nie jest plikiem z t\u0142umaczeniem dla Prune
 error.convertnamestotimes.nonames=\u017badne nazwy nie mog\u0142y zosta\u0107 zmienione na czas
 error.osmimage.failed=B\u0142\u0105d przy \u0142adowaniu obraz\u00f3w map. Sprawd\u017a po\u0142\u0105czenie z internetem.
 error.language.wrongfile=Wybrany plik nie jest plikiem z t\u0142umaczeniem dla Prune
 error.convertnamestotimes.nonames=\u017badne nazwy nie mog\u0142y zosta\u0107 zmienione na czas
+error.lookupsrtm.none=Nie znaleziono danych o wysoko\u015bci.
index cc444d064cd3475e6c14b00bd5cb8e0dbef4df56..6010a38ed1541c1a93d835f416a6054ef0239900 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=Arquivo
 
 # Menu entries
 menu.file=Arquivo
-menu.file.open=Abrir
 menu.file.addphotos=Adicionar fotos
 menu.file.save=Salvar
 menu.file.exit=Sair
 menu.file.addphotos=Adicionar fotos
 menu.file.save=Salvar
 menu.file.exit=Sair
-menu.edit=Editar
 menu.track=Track
 menu.track=Track
-menu.edit.undo=Desfazer
-menu.edit.clearundo=Limpar lista de desfazer
-menu.edit.editpoint=Editar ponto
-menu.edit.deletepoint=Remover ponto
-menu.edit.deleterange=Remover intervalo
-menu.edit.deletemarked=Remover pontos marcados
-menu.edit.interpolate=Interpolar
-menu.edit.average=Sele\u00e7\u00e3o m\u00e9dia
-menu.edit.reverse=Reverter intervalo
-menu.edit.mergetracksegments=Mesclar trechos da rota
-menu.edit.rearrange=Rearrumar pontos
-menu.edit.rearrange.start=Tudo para o in\u00edcio do arquivo
-menu.edit.rearrange.end=Tudo para o fim do arquivo
-menu.edit.rearrange.nearest=Cada um para o ponto da rota mais pr\u00f3ximo
-menu.edit.cutandmove=Recortar e mover sele\u00e7\u00e3o
-menu.select=Selecionar
+menu.track.undo=Desfazer
+menu.track.clearundo=Limpar lista de desfazer
+menu.point.editpoint=Editar ponto
+menu.point.deletepoint=Remover ponto
+menu.range.deleterange=Remover intervalo
+menu.track.deletemarked=Remover pontos marcados
+menu.range.interpolate=Interpolar
+menu.range.average=Sele\u00e7\u00e3o m\u00e9dia
+menu.range.reverse=Reverter intervalo
+menu.range.mergetracksegments=Mesclar trechos da rota
+menu.track.rearrange=Rearrumar pontos
+menu.track.rearrange.start=Tudo para o in\u00edcio do arquivo
+menu.track.rearrange.end=Tudo para o fim do arquivo
+menu.track.rearrange.nearest=Cada um para o ponto da rota mais pr\u00f3ximo
+menu.range.cutandmove=Recortar e mover sele\u00e7\u00e3o
 menu.range=Intervalo
 menu.point=Ponto
 menu.range=Intervalo
 menu.point=Ponto
-menu.select.all=Selectionar tudo
-menu.select.none=N\u00e3o selecionar nenhuns
-menu.select.start=Definir in\u00edcio do intervalo
-menu.select.end=Definir fim do intervalo
+menu.range.all=Selectionar tudo
+menu.range.none=N\u00e3o selecionar nenhuns
+menu.range.start=Definir in\u00edcio do intervalo
+menu.range.end=Definir fim do intervalo
 menu.photo=Foto
 menu.photo.saveexif=Salvar para Exif
 menu.photo.connect=Conectar ao ponto
 menu.photo=Foto
 menu.photo.saveexif=Salvar para Exif
 menu.photo.connect=Conectar ao ponto
@@ -57,8 +54,6 @@ menu.map.showscalebar=Mostrar barra de escala
 
 # Alt keys for menus
 altkey.menu.file=A
 
 # Alt keys for menus
 altkey.menu.file=A
-altkey.menu.edit=E
-altkey.menu.select=S
 altkey.menu.track=T
 altkey.menu.range=I
 altkey.menu.point=P
 altkey.menu.track=T
 altkey.menu.range=I
 altkey.menu.point=P
@@ -71,12 +66,13 @@ altkey.menu.help=J
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=S
 shortcut.menu.file.open=A
 shortcut.menu.file.load=C
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=T
+shortcut.menu.range.all=T
 shortcut.menu.help.help=J
 
 # Functions
 shortcut.menu.help.help=J
 
 # Functions
+function.open=Abrir
 function.loadfromgps=Carregar dados do GPS
 function.sendtogps=Enviar dados para o GPS
 function.exportkml=Exportar para KML
 function.loadfromgps=Carregar dados do GPS
 function.sendtogps=Enviar dados para o GPS
 function.exportkml=Exportar para KML
@@ -215,8 +211,6 @@ dialog.addtimeoffset.minutes=Minutos
 dialog.addtimeoffset.notimestamps=N\u00e3o foi poss\u00edvel adicionar uma diferen\u00e7a de tempo uma vez que esta sele\u00e7\u00e3o n\u00e3o possui nenhuma informa\u00e7\u00e3o de data-hora
 dialog.findwaypoint.intro=Insira parte do nome do ponto
 dialog.findwaypoint.search=Pesquisar
 dialog.addtimeoffset.notimestamps=N\u00e3o foi poss\u00edvel adicionar uma diferen\u00e7a de tempo uma vez que esta sele\u00e7\u00e3o n\u00e3o possui nenhuma informa\u00e7\u00e3o de data-hora
 dialog.findwaypoint.intro=Insira parte do nome do ponto
 dialog.findwaypoint.search=Pesquisar
-dialog.connect.title=Conectar foto ao ponto
-dialog.connectphoto.clonepoint=Este ponto j\u00e1 possui uma foto.\n Voc\u00ea deseja fazer uma c\u00f3pia deste ponto?
 dialog.saveexif.title=Salvar Exif
 dialog.saveexif.intro=Selecionar as fotos para salvar usando as caixas de sele\u00e7\u00e3o
 dialog.saveexif.nothingtosave=Dados das coordenadas n\u00e3o foram alterados, nada para salvar
 dialog.saveexif.title=Salvar Exif
 dialog.saveexif.intro=Selecionar as fotos para salvar usando as caixas de sele\u00e7\u00e3o
 dialog.saveexif.nothingtosave=Dados das coordenadas n\u00e3o foram alterados, nada para salvar
index e416762c00bdafdabb8484b572a71b5bb9212b33..ea0d138e1b7e14d314dc1a28a1ad2b35668f2c6c 100644 (file)
@@ -3,33 +3,30 @@
 
 # Menu entries
 menu.file=Fi\u015fier
 
 # Menu entries
 menu.file=Fi\u015fier
-menu.file.open=Deschidere fi\u015fier
 menu.file.addphotos=Adaugare foto
 menu.file.save=Salvare
 menu.file.exit=Iesire
 menu.track=Traseu
 menu.file.addphotos=Adaugare foto
 menu.file.save=Salvare
 menu.file.exit=Iesire
 menu.track=Traseu
-menu.edit=Editare
-menu.edit.undo=Anulare
-menu.edit.clearundo=\u015etergere lista de anulari
-menu.edit.editpoint=Editare punct
-menu.edit.deletepoint=\u015etergere punct
-menu.edit.deleterange=\u015etergere gama
-menu.edit.deletemarked=\u015etergere puncte marcate
-menu.edit.interpolate=Interpolare
-menu.edit.average=Mediere selectie
-menu.edit.reverse=Inversare selectie
-menu.edit.mergetracksegments=Unire segmente traseu
-menu.edit.rearrange=Rearanjare waypoint
-menu.edit.rearrange.start=Toate la inceputul fisierului
-menu.edit.rearrange.end=Toate la sfarsitul fisierului
-menu.edit.rearrange.nearest=Fiecare la punctul cel mai apropiat al traseului
-menu.edit.cutandmove=Taiere si mutare selectie
+menu.track.undo=Anulare
+menu.track.clearundo=\u015etergere lista de anulari
+menu.point.editpoint=Editare punct
+menu.point.deletepoint=\u015etergere punct
+menu.range.deleterange=\u015etergere gama
+menu.track.deletemarked=\u015etergere puncte marcate
+menu.range.interpolate=Interpolare
+menu.range.average=Mediere selectie
+menu.range.reverse=Inversare selectie
+menu.range.mergetracksegments=Unire segmente traseu
+menu.track.rearrange=Rearanjare waypoint
+menu.track.rearrange.start=Toate la inceputul fisierului
+menu.track.rearrange.end=Toate la sfarsitul fisierului
+menu.track.rearrange.nearest=Fiecare la punctul cel mai apropiat al traseului
+menu.range.cutandmove=Taiere si mutare selectie
 menu.point=Punct
 menu.point=Punct
-menu.select=Selectare
-menu.select.all=Selectare toate
-menu.select.none=Nu selecta niciun punct
-menu.select.start=Seteaza inceputul selectiei
-menu.select.end=Seteaza sfarsitul selectiei
+menu.range.all=Selectare toate
+menu.range.none=Nu selecta niciun punct
+menu.range.start=Seteaza inceputul selectiei
+menu.range.end=Seteaza sfarsitul selectiei
 menu.photo=Foto
 menu.photo.saveexif=Salveaza la Exif
 menu.photo.connect=Conecteaza la punct
 menu.photo=Foto
 menu.photo.saveexif=Salveaza la Exif
 menu.photo.connect=Conecteaza la punct
@@ -63,10 +60,11 @@ altkey.menu.help=A
 # Ctrl shortcuts for menu items
 shortcut.menu.file.open=D
 shortcut.menu.file.save=S
 # Ctrl shortcuts for menu items
 shortcut.menu.file.open=D
 shortcut.menu.file.save=S
-shortcut.menu.edit.undo=Z
-shortcut.menu.select.all=T
+shortcut.menu.track.undo=Z
+shortcut.menu.range.all=T
 
 # Functions
 
 # Functions
+function.open=Deschidere fi\u015fier
 function.loadfromgps=\u00cencarc\u0103 date de la GPS
 function.sendtogps=Trimite date spre GPS
 function.exportkml=Export\u0103 \u00eentr-un fi\u015fier KML
 function.loadfromgps=\u00cencarc\u0103 date de la GPS
 function.sendtogps=Trimite date spre GPS
 function.exportkml=Export\u0103 \u00eentr-un fi\u015fier KML
@@ -129,8 +127,6 @@ dialog.saveexif.overwrite=Suprascrie fisiere
 dialog.charts.xaxis=Axa X
 dialog.charts.yaxis=Axa Y
 dialog.distances.currentpoint=Punct curent
 dialog.charts.xaxis=Axa X
 dialog.charts.yaxis=Axa Y
 dialog.distances.currentpoint=Punct curent
-dialog.setmapbg.mapnik=Mapnik (implicit)
-dialog.setmapbg.server=Adres\u0103 server
 dialog.gpsies.column.length=Lungime
 dialog.gpsies.description=Descriere
 dialog.gpsies.nodescription=Fara descriere
 dialog.gpsies.column.length=Lungime
 dialog.gpsies.description=Descriere
 dialog.gpsies.nodescription=Fara descriere
index 20fe68933d43a403ccd5f0ea591c7cad30844b9d..59fa48f217cb05cd9d2dba4b73ba45dac704c28e 100644 (file)
@@ -3,34 +3,31 @@
 
 # Menu entries
 menu.file=Dosya
 
 # Menu entries
 menu.file=Dosya
-menu.file.open=Dosya a\u00e7
 menu.file.addphotos=Foto ekle
 menu.file.save=Kaydet
 menu.file.exit=Ç\u0131k\u0131\u015f
 menu.file.addphotos=Foto ekle
 menu.file.save=Kaydet
 menu.file.exit=Ç\u0131k\u0131\u015f
-menu.edit=D\u00fczenle
 menu.track=\u0130z
 menu.track=\u0130z
-menu.edit.undo=Geri al
-menu.edit.clearundo=Geri alma listesi s\u0131f\u0131rla
-menu.edit.editpoint=Nokta d\u00fczenle
-menu.edit.deletepoint=Noktay\u0131 sil
-menu.edit.deleterange=S\u0131ray\u0131 sil
-menu.edit.deletemarked=Se\u00e7ili noktalar\u0131 sil
-menu.edit.interpolate=\u0130nterpolasyon
-menu.edit.average=Se\u00e7me ortala
-menu.edit.reverse=S\u0131ra tersine \u00e7evir
-menu.edit.mergetracksegments=\u0130z par\u00e7alar\u0131 birle\u015ftir
-menu.edit.rearrange=Yol noktalar\u0131 yeniden diz
-menu.edit.rearrange.start=Hepsini dosyan\u0131n ba\u015f\u0131na
-menu.edit.rearrange.end=Hepsini dosyan\u0131n sonuna
-menu.edit.rearrange.nearest=En yak\u0131n iz noktaya
-menu.edit.cutandmove=Se\u00e7me kes ve ta\u015f\u0131
-menu.select=Se\u00e7
+menu.track.undo=Geri al
+menu.track.clearundo=Geri alma listesi s\u0131f\u0131rla
+menu.point.editpoint=Nokta d\u00fczenle
+menu.point.deletepoint=Noktay\u0131 sil
+menu.range.deleterange=S\u0131ray\u0131 sil
+menu.track.deletemarked=Se\u00e7ili noktalar\u0131 sil
+menu.range.interpolate=\u0130nterpolasyon
+menu.range.average=Se\u00e7me ortala
+menu.range.reverse=S\u0131ra tersine \u00e7evir
+menu.range.mergetracksegments=\u0130z par\u00e7alar\u0131 birle\u015ftir
+menu.track.rearrange=Yol noktalar\u0131 yeniden diz
+menu.track.rearrange.start=Hepsini dosyan\u0131n ba\u015f\u0131na
+menu.track.rearrange.end=Hepsini dosyan\u0131n sonuna
+menu.track.rearrange.nearest=En yak\u0131n iz noktaya
+menu.range.cutandmove=Se\u00e7me kes ve ta\u015f\u0131
 menu.range=S\u0131ra
 menu.point=Nokta
 menu.range=S\u0131ra
 menu.point=Nokta
-menu.select.all=Hepsini se\u00e7
-menu.select.none=Hi\u00e7 se\u00e7
-menu.select.start=S\u0131ran\u0131n ba\u015fkang\u0131c\u0131 se\u00e7
-menu.select.end=S\u0131ran\u0131n sonu se\u00e7
+menu.range.all=Hepsini se\u00e7
+menu.range.none=Hi\u00e7 se\u00e7
+menu.range.start=S\u0131ran\u0131n ba\u015fkang\u0131c\u0131 se\u00e7
+menu.range.end=S\u0131ran\u0131n sonu se\u00e7
 menu.photo=Foto
 menu.photo.saveexif=Exif'te kaydet
 menu.photo.connect=Noktaya ba\u011flan
 menu.photo=Foto
 menu.photo.saveexif=Exif'te kaydet
 menu.photo.connect=Noktaya ba\u011flan
@@ -44,7 +41,6 @@ menu.view.browser.mapquest=Mapquest
 menu.view.browser.yahoo=Yahoo haritalar\u0131
 menu.view.browser.bing=Bing haritalar\u0131
 menu.settings=Ayarlar
 menu.view.browser.yahoo=Yahoo haritalar\u0131
 menu.view.browser.bing=Bing haritalar\u0131
 menu.settings=Ayarlar
-menu.settings.showpace=H\u0131z\u0131 g\u00f6r\u00fcnt\u00fcle
 menu.help=Yard\u0131m
 # Popup menu for map
 menu.map.zoomin=Yak\u0131nla\u015ft\u0131r
 menu.help=Yard\u0131m
 # Popup menu for map
 menu.map.zoomin=Yak\u0131nla\u015ft\u0131r
@@ -56,8 +52,6 @@ menu.map.showscalebar=\u00d6l\u00e7e\u011fi g\u00f6r\u00fcnt\u00fcle
 
 # Alt keys for menus
 altkey.menu.file=D
 
 # Alt keys for menus
 altkey.menu.file=D
-altkey.menu.edit=Z
-altkey.menu.select=S
 altkey.menu.track=Z
 altkey.menu.range=S
 altkey.menu.point=N
 altkey.menu.track=Z
 altkey.menu.range=S
 altkey.menu.point=N
@@ -70,12 +64,13 @@ altkey.menu.help=Y
 shortcut.menu.file.open=A
 shortcut.menu.file.load=L
 shortcut.menu.file.save=K
 shortcut.menu.file.open=A
 shortcut.menu.file.load=L
 shortcut.menu.file.save=K
-shortcut.menu.edit.undo=Z
+shortcut.menu.track.undo=Z
 shortcut.menu.edit.compress=C
 shortcut.menu.edit.compress=C
-shortcut.menu.select.all=A
+shortcut.menu.range.all=A
 shortcut.menu.help.help=Y
 
 # Functions
 shortcut.menu.help.help=Y
 
 # Functions
+function.open=Dosya a\u00e7
 function.loadfromgps=GPS'den veri al
 function.sendtogps=GPS'e veri g\u00f6nder
 function.exportkml=Ver KML olarak
 function.loadfromgps=GPS'den veri al
 function.sendtogps=GPS'e veri g\u00f6nder
 function.exportkml=Ver KML olarak
@@ -270,7 +265,6 @@ dialog.saveconfig.prune.gpsbabelpath=gpsbabel'in yeriyolu
 dialog.saveconfig.prune.exiftoolpath=exiftool'un yeriyolu
 dialog.saveconfig.prune.mapserverindex=Harita sunucunun index
 dialog.saveconfig.prune.mapserverurl=Harita sunucunun adresi
 dialog.saveconfig.prune.exiftoolpath=exiftool'un yeriyolu
 dialog.saveconfig.prune.mapserverindex=Harita sunucunun index
 dialog.saveconfig.prune.mapserverurl=Harita sunucunun adresi
-dialog.saveconfig.prune.showpace=H\u0131z\u0131 g\u00f6r\u00fcnt\u00fcle
 dialog.saveconfig.prune.kmzimagewidth=KMZ resim geni\u015fli\u011fi
 dialog.saveconfig.prune.kmzimageheight=KMZ resim y\u00fcksekli\u011fi
 dialog.setpaths.intro=\u0130ste\u011fe ba\u011fl\u0131 a\u015fa\u011f\u0131daki uygulamalar\u0131n veriyolu kaydedebilirsin:
 dialog.saveconfig.prune.kmzimagewidth=KMZ resim geni\u015fli\u011fi
 dialog.saveconfig.prune.kmzimageheight=KMZ resim y\u00fcksekli\u011fi
 dialog.setpaths.intro=\u0130ste\u011fe ba\u011fl\u0131 a\u015fa\u011f\u0131daki uygulamalar\u0131n veriyolu kaydedebilirsin:
index ba1c391460f3b6b22c62d7e75f890d387ae3b112..5bf076411332602d99a8d0710afe569259dc11ba 100644 (file)
@@ -3,31 +3,28 @@
 
 # Menu entries
 menu.file=\u6587\u4ef6
 
 # Menu entries
 menu.file=\u6587\u4ef6
-menu.file.open=\u6253\u5f00
 menu.file.addphotos=\u6dfb\u52a0\u76f8\u7247
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u9000\u51fa
 menu.file.addphotos=\u6dfb\u52a0\u76f8\u7247
 menu.file.save=\u4fdd\u5b58
 menu.file.exit=\u9000\u51fa
-menu.edit=\u7f16\u8f91
-menu.edit.undo=\u64a4\u9500
-menu.edit.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
-menu.edit.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
-menu.edit.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
-menu.edit.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
-menu.edit.deletemarked=\u5220\u9664\u5df2\u6807\u793a\u8f68\u8ff9\u70b9
-menu.edit.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
-menu.edit.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
-menu.edit.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
-menu.edit.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
-menu.edit.rearrange=\u822a\u70b9\u91cd\u7f6e
-menu.edit.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
-menu.edit.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
-menu.edit.rearrange.nearest=\u81f3\u6700\u8fd1\u8f68\u8ff9\u70b9
-menu.edit.cutandmove=\u79fb\u52a8
-menu.select=\u9009\u62e9
-menu.select.all=\u5168\u9009
-menu.select.none=\u64a4\u9500\u9009\u62e9
-menu.select.start=\u8bbe\u7f6e\u8d77\u70b9
-menu.select.end=\u8bbe\u7f6e\u672b\u70b9
+menu.track.undo=\u64a4\u9500
+menu.track.clearundo=\u6e05\u9664\u64a4\u9500\u6e05\u5355
+menu.point.editpoint=\u7f16\u8f91\u8f68\u8ff9\u70b9
+menu.point.deletepoint=\u5220\u9664\u8f68\u8ff9\u70b9
+menu.range.deleterange=\u5220\u9664\u8f68\u8ff9\u70b9\u6bb5
+menu.track.deletemarked=\u5220\u9664\u5df2\u6807\u793a\u8f68\u8ff9\u70b9
+menu.range.interpolate=\u63d2\u5165\u8f68\u8ff9\u70b9
+menu.range.average=\u8bbe\u7f6e\u5e73\u5747\u8f68\u8ff9\u70b9
+menu.range.reverse=\u8f68\u8ff9\u70b9\u53cd\u5411
+menu.range.mergetracksegments=\u5408\u5e76\u8f68\u8ff9\u6bb5
+menu.track.rearrange=\u822a\u70b9\u91cd\u7f6e
+menu.track.rearrange.start=\u81f3\u8d77\u59cb\u4f4d\u7f6e
+menu.track.rearrange.end=\u81f3\u672b\u4f4d\u7f6e
+menu.track.rearrange.nearest=\u81f3\u6700\u8fd1\u8f68\u8ff9\u70b9
+menu.range.cutandmove=\u79fb\u52a8
+menu.range.all=\u5168\u9009
+menu.range.none=\u64a4\u9500\u9009\u62e9
+menu.range.start=\u8bbe\u7f6e\u8d77\u70b9
+menu.range.end=\u8bbe\u7f6e\u672b\u70b9
 menu.photo=\u76f8\u7247
 menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
 menu.photo.connect=\u94fe\u63a5\u76f8\u7247
 menu.photo=\u76f8\u7247
 menu.photo.saveexif=\u5750\u6807\u4fdd\u5b58\u81f3Exif
 menu.photo.connect=\u94fe\u63a5\u76f8\u7247
@@ -40,7 +37,6 @@ menu.view.browser.openstreetmap=Openstreet\u5730\u56fe
 menu.view.browser.mapquest=Mapquest\u5730\u56fe
 menu.view.browser.yahoo=Yahoo\u5730\u56fe
 menu.settings=\u8bbe\u7f6e
 menu.view.browser.mapquest=Mapquest\u5730\u56fe
 menu.view.browser.yahoo=Yahoo\u5730\u56fe
 menu.settings=\u8bbe\u7f6e
-menu.settings.showpace=\u663e\u793a\u6b65\u901f
 menu.help=\u5e2e\u52a9
 # Popup menu for map
 menu.map.zoomin=\u653e\u5927
 menu.help=\u5e2e\u52a9
 # Popup menu for map
 menu.map.zoomin=\u653e\u5927
@@ -53,6 +49,7 @@ menu.map.showmap=\u663e\u793a\u5730\u56fe
 menu.map.showscalebar=\u663e\u793a\u6bd4\u4f8b\u5c3a
 
 # Functions
 menu.map.showscalebar=\u663e\u793a\u6bd4\u4f8b\u5c3a
 
 # Functions
+function.open=\u6253\u5f00
 function.loadfromgps=\u4eceGPS\u5bfc\u5165
 function.sendtogps=\u53d1\u9001\u81f3GPS
 function.exportkml=\u8f93\u51faKML\u6587\u4ef6
 function.loadfromgps=\u4eceGPS\u5bfc\u5165
 function.sendtogps=\u53d1\u9001\u81f3GPS
 function.exportkml=\u8f93\u51faKML\u6587\u4ef6
@@ -176,8 +173,6 @@ dialog.addtimeoffset.minutes=\u5206\u949f
 dialog.addtimeoffset.notimestamps=\u4e0d\u80fd\u6dfb\u52a0\u65f6\u95f4\u56e0\u4e3a\u6b64\u6bb5\u4e0d\u542b\u65f6\u95f4\u4fe1\u606f
 dialog.findwaypoint.intro=\u8f93\u5165\u90e8\u5206\u822a\u70b9\u540d
 dialog.findwaypoint.search=\u641c\u7d22
 dialog.addtimeoffset.notimestamps=\u4e0d\u80fd\u6dfb\u52a0\u65f6\u95f4\u56e0\u4e3a\u6b64\u6bb5\u4e0d\u542b\u65f6\u95f4\u4fe1\u606f
 dialog.findwaypoint.intro=\u8f93\u5165\u90e8\u5206\u822a\u70b9\u540d
 dialog.findwaypoint.search=\u641c\u7d22
-dialog.connect.title=\u94fe\u63a5\u7167\u7247\u548c\u822a\u70b9
-dialog.connectphoto.clonepoint=\u6b64\u8f68\u8ff9\u70b9\u5df2\u6709\u50cf\u7247\n\u662f\u5426\u590d\u5236\u822a\u70b9\uff1f
 dialog.saveexif.title=\u4fdd\u5b58Exif
 dialog.saveexif.intro=\u9009\u62e9\u8981\u4fdd\u5b58\u7684\u76f8\u7247
 dialog.saveexif.nothingtosave=\u5750\u6807\u672a\u6539\u53d8\uff0c\u65e0\u4fdd\u5b58\u5185\u5bb9
 dialog.saveexif.title=\u4fdd\u5b58Exif
 dialog.saveexif.intro=\u9009\u62e9\u8981\u4fdd\u5b58\u7684\u76f8\u7247
 dialog.saveexif.nothingtosave=\u5750\u6807\u672a\u6539\u53d8\uff0c\u65e0\u4fdd\u5b58\u5185\u5bb9
@@ -292,7 +287,6 @@ dialog.saveconfig.prune.gpsbabelpath=gpsbabel\u8def\u5f84
 dialog.saveconfig.prune.exiftoolpath=exiftool\u8def\u5f84
 dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56fe\u7801(1-4)
 dialog.saveconfig.prune.mapserverurl=\u90094\u65f6\u5730\u56fe\u670d\u52a1\u5668URL
 dialog.saveconfig.prune.exiftoolpath=exiftool\u8def\u5f84
 dialog.saveconfig.prune.mapserverindex=\u80cc\u666f\u5730\u56fe\u7801(1-4)
 dialog.saveconfig.prune.mapserverurl=\u90094\u65f6\u5730\u56fe\u670d\u52a1\u5668URL
-dialog.saveconfig.prune.showpace=\u663e\u793a\u6b65\u901f
 dialog.saveconfig.prune.kmzimagewidth=KMZ\u56fe\u50cf\u5bbd\u5ea6
 dialog.saveconfig.prune.kmzimageheight=KMZ\u56fe\u50cf\u9ad8\u5ea6
 dialog.setpaths.intro=\u82e5\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
 dialog.saveconfig.prune.kmzimagewidth=KMZ\u56fe\u50cf\u5bbd\u5ea6
 dialog.saveconfig.prune.kmzimageheight=KMZ\u56fe\u50cf\u9ad8\u5ea6
 dialog.setpaths.intro=\u82e5\u9700\u8981\uff0c\u53ef\u8bbe\u5b9a\u5916\u6302\u7a0b\u5e8f\u8def\u5f84
index 08b29fad02e6b32ec2cfc6bafa663869d76cbefa..fabcb4dde5d6e7bfe14d849f18189ba2f8f1d006 100644 (file)
@@ -21,15 +21,14 @@ import tim.prune.I18nManager;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
 import tim.prune.config.Config;
 import tim.prune.data.Altitude;
 import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
 import tim.prune.data.LatLonRectangle;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
 import tim.prune.data.Photo;
 import tim.prune.data.Timestamp;
 import tim.prune.data.LatLonRectangle;
 import tim.prune.data.Latitude;
 import tim.prune.data.Longitude;
 import tim.prune.data.Photo;
 import tim.prune.data.Timestamp;
-import tim.prune.drew.jpeg.ExifReader;
-import tim.prune.drew.jpeg.JpegData;
-import tim.prune.drew.jpeg.JpegException;
-import tim.prune.drew.jpeg.Rational;
+import tim.prune.jpeg.ExifGateway;
+import tim.prune.jpeg.JpegData;
 
 /**
  * Class to manage the loading of Jpegs and dealing with the GPS data from them
 
 /**
  * Class to manage the loading of Jpegs and dealing with the GPS data from them
@@ -250,19 +249,19 @@ public class JpegLoader implements Runnable
 
                // Create Photo object
                Photo photo = new Photo(inFile);
 
                // Create Photo object
                Photo photo = new Photo(inFile);
+               if (inFile.exists() && inFile.canRead()) {
+                       _fileCounts[1]++; // jpeg found
+               }
                // Try to get information out of exif
                // Try to get information out of exif
-               try
+               JpegData jpegData = ExifGateway.getJpegData(inFile);
+               Timestamp timestamp = null;
+               if (jpegData != null)
                {
                {
-                       JpegData jpegData = new ExifReader(inFile).extract();
-                       _fileCounts[1]++; // jpeg found (no exception thrown)
                        if (jpegData.getExifDataPresent())
                                {_fileCounts[2]++;} // exif found
                        if (jpegData.getExifDataPresent())
                                {_fileCounts[2]++;} // exif found
-                       if (jpegData.isValid())
+                       if (jpegData.isGpsValid())
                        {
                        {
-                               if (jpegData.getGpsDatestamp() != null && jpegData.getGpsTimestamp() != null)
-                               {
-                                       photo.setTimestamp(createTimestamp(jpegData.getGpsDatestamp(), jpegData.getGpsTimestamp()));
-                               }
+                               timestamp = createTimestamp(jpegData.getGpsDatestamp(), jpegData.getGpsTimestamp());
                                // Make DataPoint and attach to Photo
                                DataPoint point = createDataPoint(jpegData);
                                point.setPhoto(photo);
                                // Make DataPoint and attach to Photo
                                DataPoint point = createDataPoint(jpegData);
                                point.setPhoto(photo);
@@ -272,19 +271,21 @@ public class JpegLoader implements Runnable
                                _fileCounts[3]++;
                        }
                        // Use exif timestamp if gps timestamp not available
                                _fileCounts[3]++;
                        }
                        // Use exif timestamp if gps timestamp not available
-                       if (photo.getTimestamp() == null && jpegData.getOriginalTimestamp() != null)
-                       {
-                               photo.setTimestamp(createTimestamp(jpegData.getOriginalTimestamp()));
+                       if (timestamp == null && jpegData.getOriginalTimestamp() != null) {
+                               timestamp = createTimestamp(jpegData.getOriginalTimestamp());
                        }
                        photo.setExifThumbnail(jpegData.getThumbnailImage());
                        // Also extract orientation tag for setting rotation state of photo
                        photo.setRotation(jpegData.getRequiredRotation());
                }
                        }
                        photo.setExifThumbnail(jpegData.getThumbnailImage());
                        // Also extract orientation tag for setting rotation state of photo
                        photo.setRotation(jpegData.getRequiredRotation());
                }
-               catch (JpegException jpe) { // don't list errors, just count them
-               }
                // Use file timestamp if exif timestamp isn't available
                // Use file timestamp if exif timestamp isn't available
-               if (photo.getTimestamp() == null) {
-                       photo.setTimestamp(new Timestamp(inFile.lastModified()));
+               if (timestamp == null) {
+                       timestamp = new Timestamp(inFile.lastModified());
+               }
+               // Apply timestamp to photo and its point (if any)
+               photo.setTimestamp(timestamp);
+               if (photo.getDataPoint() != null) {
+                       photo.getDataPoint().setFieldValue(Field.TIMESTAMP, timestamp.getText(Timestamp.FORMAT_ISO_8601), false);
                }
                // Check the criteria for adding the photo - check whether the photo has coordinates and if so if they're within the rectangle
                if ( (photo.getDataPoint() != null || _noExifCheckbox.isSelected())
                }
                // Check the criteria for adding the photo - check whether the photo has coordinates and if so if they're within the rectangle
                if ( (photo.getDataPoint() != null || _noExifCheckbox.isSelected())
@@ -350,26 +351,25 @@ public class JpegLoader implements Runnable
                        inData.getLongitudeRef() == 'E' || inData.getLongitudeRef() == 'e');
                Longitude longitude = new Longitude(lonval, Longitude.FORMAT_DEG_MIN_SEC);
                Altitude altitude = null;
                        inData.getLongitudeRef() == 'E' || inData.getLongitudeRef() == 'e');
                Longitude longitude = new Longitude(lonval, Longitude.FORMAT_DEG_MIN_SEC);
                Altitude altitude = null;
-               if (inData.getAltitude() != null)
-               {
-                       altitude = new Altitude(inData.getAltitude().intValue(), Altitude.Format.METRES);
+               if (inData.hasAltitude()) {
+                       altitude = new Altitude(inData.getAltitude(), Altitude.Format.METRES);
                }
                return new DataPoint(latitude, longitude, altitude);
        }
 
 
        /**
                }
                return new DataPoint(latitude, longitude, altitude);
        }
 
 
        /**
-        * Convert an array of 3 Rational numbers into a double coordinate value
-        * @param inRationals array of three Rational objects
+        * Convert an array of 3 doubles (deg-min-sec) into a double coordinate value
+        * @param inValues array of three doubles for deg-min-sec
         * @param isPositive true for positive hemisphere, for positive double value
         * @return double value of coordinate, either positive or negative
         */
         * @param isPositive true for positive hemisphere, for positive double value
         * @return double value of coordinate, either positive or negative
         */
-       private static double getCoordinateDoubleValue(Rational[] inRationals, boolean isPositive)
+       private static double getCoordinateDoubleValue(double[] inValues, boolean isPositive)
        {
        {
-               if (inRationals == null || inRationals.length != 3) return 0.0;
-               double value = inRationals[0].doubleValue()        // degrees
-                       + inRationals[1].doubleValue() / 60.0          // minutes
-                       + inRationals[2].doubleValue() / 60.0 / 60.0;  // seconds
+               if (inValues == null || inValues.length != 3) return 0.0;
+               double value = inValues[0]        // degrees
+                       + inValues[1] / 60.0          // minutes
+                       + inValues[2] / 60.0 / 60.0;  // seconds
                // make sure it's the correct sign
                value = Math.abs(value);
                if (!isPositive) value = -value;
                // make sure it's the correct sign
                value = Math.abs(value);
                if (!isPositive) value = -value;
@@ -378,15 +378,18 @@ public class JpegLoader implements Runnable
 
 
        /**
 
 
        /**
-        * Use the given Rational values to create a timestamp
-        * @param inDate rationals describing date
-        * @param inTime rationals describing time
+        * Use the given int values to create a timestamp
+        * @param inDate ints describing date
+        * @param inTime ints describing time
         * @return Timestamp object corresponding to inputs
         */
         * @return Timestamp object corresponding to inputs
         */
-       private static Timestamp createTimestamp(Rational[] inDate, Rational[] inTime)
+       private static Timestamp createTimestamp(int[] inDate, int[] inTime)
        {
        {
-               return new Timestamp(inDate[0].intValue(), inDate[1].intValue(), inDate[2].intValue(),
-                       inTime[0].intValue(), inTime[1].intValue(), inTime[2].intValue());
+               if (inDate == null || inTime == null || inDate.length != 3 || inTime.length != 3) {
+                       return null;
+               }
+               return new Timestamp(inDate[0], inDate[1], inDate[2],
+                       inTime[0], inTime[1], inTime[2]);
        }
 
 
        }
 
 
index 090bb6d3a9a0c738b3ad1e71c64e512a9e0a4922..76ed15785dc1fff93ec18661790e8c9955539711 100644 (file)
@@ -36,6 +36,7 @@ public class NmeaFileLoader
        {
                BufferedReader reader = null;
                ArrayList<NmeaMessage> messages = new ArrayList<NmeaMessage>();
        {
                BufferedReader reader = null;
                ArrayList<NmeaMessage> messages = new ArrayList<NmeaMessage>();
+               String lastDate = null;
                try
                {
                        reader = new BufferedReader(new FileReader(inFile));
                try
                {
                        reader = new BufferedReader(new FileReader(inFile));
@@ -46,17 +47,32 @@ public class NmeaFileLoader
                                // Try to make an NmeaMessage object for each line of file
                                if (currLine.trim().length() > 0)
                                {
                                // Try to make an NmeaMessage object for each line of file
                                if (currLine.trim().length() > 0)
                                {
-                                       NmeaMessage message = processLine(currLine);
+                                       NmeaMessage message = processGGA(currLine);
                                        if (message != null)
                                        {
                                        if (message != null)
                                        {
-                                               if (message.hasFix()) {
+                                               if (message.hasFix())
+                                               {
                                                        message.setSegment(newSegment);
                                                        message.setSegment(newSegment);
+                                                       message.setDate(lastDate);
                                                        // add message to list
                                                        messages.add(message);
                                                }
                                                // Start a new segment if fix lost
                                                newSegment = !message.hasFix();
                                        }
                                                        // add message to list
                                                        messages.add(message);
                                                }
                                                // Start a new segment if fix lost
                                                newSegment = !message.hasFix();
                                        }
+                                       else {
+                                               String date = getDateFromRMC(currLine);
+                                               if (date != null)
+                                               {
+                                                       if (lastDate == null && !messages.isEmpty()) {
+                                                               // Backfill first few messages received before the first date
+                                                               for (int m=0; m<messages.size(); m++) {
+                                                                       messages.get(m).setDate(date);
+                                                               }
+                                                       }
+                                                       lastDate = date;
+                                               }
+                                       }
                                }
                                // Read next line, if any
                                currLine = reader.readLine();
                                }
                                // Read next line, if any
                                currLine = reader.readLine();
@@ -68,8 +84,7 @@ public class NmeaFileLoader
                finally
                {
                        // close file ignoring errors
                finally
                {
                        // close file ignoring errors
-                       try
-                       {
+                       try {
                                if (reader != null) reader.close();
                        }
                        catch (Exception e) {}
                                if (reader != null) reader.close();
                        }
                        catch (Exception e) {}
@@ -82,17 +97,16 @@ public class NmeaFileLoader
        }
 
        /**
        }
 
        /**
-        * Process the given NMEA line and return the message
+        * Process the given GGA sentence and return the message
         * @param inLine line to process
         * @return message object
         */
         * @param inLine line to process
         * @return message object
         */
-       private static NmeaMessage processLine(String inLine)
+       private static NmeaMessage processGGA(String inLine)
        {
                // Only consider lines which are long enough and begin with the GPS position sentence
                if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPGGA")) {
                        return null;
                }
        {
                // Only consider lines which are long enough and begin with the GPS position sentence
                if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPGGA")) {
                        return null;
                }
-               // TODO: May be possible to pull date out of GPRMC messages, but then need to back-populate
                // Assume comma delimiter, split into array
                String[] splitLine = inLine.split(",");
                if (splitLine != null && splitLine.length >= 10)
                // Assume comma delimiter, split into array
                String[] splitLine = inLine.split(",");
                if (splitLine != null && splitLine.length >= 10)
@@ -107,6 +121,27 @@ public class NmeaFileLoader
                return null;
        }
 
                return null;
        }
 
+       /**
+        * Process the given MRC sentence and return the date
+        * @param inLine line to process
+        * @return date, if any
+        */
+       private static String getDateFromRMC(String inLine)
+       {
+               // Only consider lines which are long enough and begin with the RMC sentence
+               if (inLine == null || inLine.length() < 20 || !inLine.startsWith("$GPRMC")) {
+                       return null;
+               }
+               // Assume comma delimiter, split into array
+               String[] splitLine = inLine.split(",");
+               if (splitLine != null && splitLine.length >= 10)
+               {
+                       return splitLine[9]; // date in position 9
+               }
+               // Couldn't parse it, return null
+               return null;
+       }
+
        /**
         * Make an object array from the data list
         * @param inList list of messages
        /**
         * Make an object array from the data list
         * @param inList list of messages
index e524e3922c7e5b69b2ba7d4580e035c3dbdbaeac..83f5382b5e0b32b67e2c7f6e82fe1d64dad34059 100644 (file)
@@ -11,6 +11,7 @@ public class NmeaMessage
        private String _longitude = null;
        private String _altitude = null;
        private String _timestamp = null;
        private String _longitude = null;
        private String _altitude = null;
        private String _timestamp = null;
+       private String _date = null;
        private boolean _fix = false;
        private boolean _segment = false;
 
        private boolean _fix = false;
        private boolean _segment = false;
 
@@ -47,6 +48,13 @@ public class NmeaMessage
                _segment = inSegment;
        }
 
                _segment = inSegment;
        }
 
+       /**
+        * @param inDate date from MRC sentence
+        */
+       public void setDate(String inDate) {
+               _date = inDate;
+       }
+
        /**
         * @return String array for loading
         */
        /**
         * @return String array for loading
         */
@@ -83,6 +91,17 @@ public class NmeaMessage
                try
                {
                        Calendar cal = Calendar.getInstance();
                try
                {
                        Calendar cal = Calendar.getInstance();
+                       // use date if available (today if not)
+                       if (_date != null && _date.length() == 6) {
+                               try {
+                                       cal.set(Calendar.DAY_OF_MONTH, Integer.parseInt(_date.substring(0, 2)));
+                                       cal.set(Calendar.MONTH, Integer.parseInt(_date.substring(2, 4))-1); // month starts at zero
+                                       int year = Integer.parseInt(_date.substring(4, 6));
+                                       if (year < 80) {year += 2000;} else {year += 1900;} // two-digit year hack
+                                       cal.set(Calendar.YEAR, year);
+                               }
+                               catch (Exception e) {} // ignore exceptions for date, still take time
+                       }
                        cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(_timestamp.substring(0, 2)));
                        cal.set(Calendar.MINUTE, Integer.parseInt(_timestamp.substring(2, 4)));
                        cal.set(Calendar.SECOND, Integer.parseInt(_timestamp.substring(4, 6)));
                        cal.set(Calendar.HOUR_OF_DAY, Integer.parseInt(_timestamp.substring(0, 2)));
                        cal.set(Calendar.MINUTE, Integer.parseInt(_timestamp.substring(2, 4)));
                        cal.set(Calendar.SECOND, Integer.parseInt(_timestamp.substring(4, 6)));
index dfeec526cb0ddfe190d76621cf7ac1747ea41130..2d0f1693226cced1a8dd8aafd057d32fd506e936 100644 (file)
@@ -80,7 +80,7 @@ public class ZipFileLoader
                        }
                }
                catch (Exception e) {
                        }
                }
                catch (Exception e) {
-                       System.err.println("Error: " + e.getClass().getName() + " -message= " + e.getMessage());
+                       System.err.println("ZipFile Error: " + e.getClass().getName() + " -message= " + e.getMessage());
                }
        }
 
                }
        }
 
@@ -125,7 +125,7 @@ public class ZipFileLoader
                        }
                }
                catch (Exception e) {
                        }
                }
                catch (Exception e) {
-                       System.err.println("Error: " + e.getClass().getName() + " -message= " + e.getMessage());
+                       System.err.println("ZipStream Error: " + e.getClass().getName() + " -message= " + e.getMessage());
                }
        }
 }
                }
        }
 }
index 8108b006b3fd7c749bb03627e634ddf7df390677..355ac71ec52e595156f13665a02f06480c22149d 100644 (file)
@@ -1,5 +1,5 @@
-Prune version 9
-===============
+Prune version 10
+================
 
 Prune is an application for viewing, editing and managing coordinate data from GPS systems,
 including format conversion, charting and photo correlation.
 
 Prune is an application for viewing, editing and managing coordinate data from GPS systems,
 including format conversion, charting and photo correlation.
@@ -17,7 +17,7 @@ Running
 =======
 
 To run Prune from the jar file, simply call it from a command prompt or shell:
 =======
 
 To run Prune from the jar file, simply call it from a command prompt or shell:
-   java -jar prune_09.jar
+   java -jar prune_10.jar
 
 If the jar file is saved in a different directory, you will need to include the path.
 Depending on your system settings, you may be able to click or double-click on the jar file
 
 If the jar file is saved in a different directory, you will need to include the path.
 Depending on your system settings, you may be able to click or double-click on the jar file
@@ -25,7 +25,19 @@ in a file manager window to execute it.  A shortcut, menu item, alias, desktop i
 or other link can of course be made should you wish.
 
 To specify a language other than the default, use an additional parameter, eg:
 or other link can of course be made should you wish.
 
 To specify a language other than the default, use an additional parameter, eg:
-   java -jar prune_09.jar --lang=DE
+   java -jar prune_10.jar --lang=DE
+
+New with version 10
+===================
+
+The following features were added since version 9:
+  - Function to lookup altitudes using SRTM data from the Space Shuttle
+  - Choice between altitude profile and speed profile in main view
+  - Caching of map tiles to disk for faster access
+  - Offline mode where maps are only retrieved from disk
+  - Storage of multiple custom map sources, not just one custom one
+  - Use of maps with multiple layers (like maps-for-free)
+  - Use of cloudmade maps
 
 New with version 9
 ==================
 
 New with version 9
 ==================
index ef1f3d56839483af8a80c078e8a4f29d91ed7aca..b7a339904288badc340f2897e7e7caebb08e71fc 100644 (file)
@@ -56,7 +56,7 @@ public class GpxCacher extends DefaultHandler
                                        saxParser.parse(new GZIPInputStream(new FileInputStream(inInfo.getFile())), this);
                                }
                                else {
                                        saxParser.parse(new GZIPInputStream(new FileInputStream(inInfo.getFile())), this);
                                }
                                else {
-                                       System.out.println("Unrecognised file type: " + inInfo.getFile().getName());
+                                       System.out.println("GpxCacher unrecognised file type: " + inInfo.getFile().getName());
                                }
                        } catch (Exception e) {
                                // TODO: Handle errors here with a list of warnings?
                                }
                        } catch (Exception e) {
                                // TODO: Handle errors here with a list of warnings?
diff --git a/tim/prune/undo/UndoLookupSrtm.java b/tim/prune/undo/UndoLookupSrtm.java
new file mode 100644 (file)
index 0000000..2672bd5
--- /dev/null
@@ -0,0 +1,64 @@
+package tim.prune.undo;
+
+import tim.prune.I18nManager;
+import tim.prune.UpdateMessageBroker;
+import tim.prune.data.DataPoint;
+import tim.prune.data.Field;
+import tim.prune.data.Track;
+import tim.prune.data.TrackInfo;
+
+/**
+ * Undo lookup of altitudes from SRTM data
+ */
+public class UndoLookupSrtm implements UndoOperation
+{
+       /** DataPoint objects which didn't have altitudes before */
+       private DataPoint[] _points;
+
+
+       /**
+        * Constructor
+        * @param inTrackInfo track info object
+        */
+       public UndoLookupSrtm(TrackInfo inTrackInfo)
+       {
+               Track track = inTrackInfo.getTrack();
+               int numPoints = track.getNumPoints();
+               // Make array of points without altitudes
+               _points = new DataPoint[numPoints];
+               for (int i=0; i<numPoints; i++) {
+                       DataPoint point = track.getPoint(i);
+                       if (!point.hasAltitude()) {
+                               _points[i] = point;
+                       }
+               }
+       }
+
+
+       /**
+        * @return description of operation
+        */
+       public String getDescription()
+       {
+               return I18nManager.getText("undo.lookupsrtm");
+       }
+
+
+       /**
+        * Perform the undo operation on the given Track
+        * @param inTrackInfo TrackInfo object on which to perform the operation
+        */
+       public void performUndo(TrackInfo inTrackInfo) throws UndoException
+       {
+               // Loop through points again, and reset altitudes if they have one
+               final int numPoints = _points.length;
+               for (int i=0; i<numPoints; i++) {
+                       DataPoint point = _points[i];
+                       if (point != null && point.hasAltitude()) {
+                               point.setFieldValue(Field.ALTITUDE, null, true);
+                       }
+               }
+               _points = null;
+               UpdateMessageBroker.informSubscribers();
+       }
+}