Ticket #21575: 21575.patch
| File 21575.patch, 37.1 KB (added by , 4 years ago) |
|---|
-
plugins/ElevationProfile/.project
diff --git a/plugins/ElevationProfile/.project b/plugins/ElevationProfile/.project index 091983087..fa9f47f0a 100644
a b 24 24 <natures> 25 25 <nature>org.eclipse.jdt.core.javanature</nature> 26 26 <nature>net.sf.eclipsecs.core.CheckstyleNature</nature> 27 <nature>org.apache.ivyde.eclipse.ivynature</nature> 27 28 </natures> 28 29 </projectDescription> -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java index da02596f8..e1ebb3754 100644
a b import java.util.ArrayList; 5 5 import java.util.Calendar; 6 6 import java.util.GregorianCalendar; 7 7 import java.util.List; 8 import java.util.Optional; 8 9 9 10 import org.openstreetmap.josm.data.Bounds; 10 11 import org.openstreetmap.josm.data.SystemOfMeasurement; 12 import org.openstreetmap.josm.data.coor.ILatLon; 11 13 import org.openstreetmap.josm.data.coor.LatLon; 12 14 import org.openstreetmap.josm.data.gpx.WayPoint; 13 15 import org.openstreetmap.josm.plugins.elevation.gpx.GeoidCorrectionKind; … … public final class ElevationHelper { 34 36 35 37 private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None; 36 38 37 /** The HGT reader instance. */38 private static final HgtReader hgt = new HgtReader();39 40 39 /** 41 40 * Gets the current mode of GEOID correction. 42 41 */ … … public final class ElevationHelper { 165 164 * @return The z coordinate or {@link Double#NaN}, if elevation value could not be obtained 166 165 * not height attribute. 167 166 */ 168 public static double getSrtmElevation( LatLon ll) {167 public static double getSrtmElevation(ILatLon ll) { 169 168 if (ll != null) { 170 169 // Try to read data from SRTM file 171 170 // TODO: Option to switch this off 172 double eleHgt = hgt.getElevationFromHgt(ll);171 double eleHgt = HgtReader.getElevationFromHgt(ll); 173 172 174 173 if (isValidElevation(eleHgt)) { 175 174 return eleHgt; … … public final class ElevationHelper { 178 177 return NO_ELEVATION; 179 178 } 180 179 180 /** 181 * Get the bounds for the pixel elevation for the latitude 182 * @param location The location to get 183 * @return The bounds for the elevation area 184 */ 185 public static Optional<Bounds> getBounds(ILatLon location) { 186 if (location != null) { 187 return HgtReader.getBounds(location); 188 } 189 return Optional.empty(); 190 } 191 181 192 /** 182 193 * Checks given area for SRTM data. 183 194 * … … public final class ElevationHelper { 251 262 if (wpt == null) return -1; 252 263 253 264 Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance 254 calendar.setTime (wpt.getDate());// assigns calendar to given date265 calendar.setTimeInMillis(wpt.getTimeInMillis()); // assigns calendar to given date 255 266 return calendar.get(Calendar.HOUR_OF_DAY); 256 267 } 257 268 … … public final class ElevationHelper { 262 273 if (wpt == null) return -1; 263 274 264 275 Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance 265 calendar.setTime (wpt.getDate());// assigns calendar to given date276 calendar.setTimeInMillis(wpt.getTimeInMillis()); // assigns calendar to given date 266 277 return calendar.get(Calendar.MINUTE); 267 278 } 268 279 } -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java index 20929ab30..d43cae774 100644
a b import static org.openstreetmap.josm.tools.I18n.tr; 5 5 6 6 import java.awt.Color; 7 7 8 import org.openstreetmap.josm.actions.ExtensionFileFilter; 8 9 import org.openstreetmap.josm.gui.IconToggleButton; 9 10 import org.openstreetmap.josm.gui.MainApplication; 10 11 import org.openstreetmap.josm.gui.MainMenu; … … public class ElevationProfilePlugin extends Plugin { 32 33 super(info); 33 34 34 35 createColorMaps(); 36 ExtensionFileFilter.addImporter(new HgtFileImporter()); 35 37 36 38 // TODO: Disable this view as long as it is not stable 37 39 MainMenu.add(MainApplication.getMenu().imagerySubMenu, new AddElevationLayerAction(), false, 0); -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java index 000d24a73..7479c3912 100644
a b 2 2 package org.openstreetmap.josm.plugins.elevation; 3 3 4 4 import java.io.File; 5 import java.io.FileInputStream;6 5 import java.io.FileNotFoundException; 6 import java.io.IOException; 7 import java.io.InputStream; 7 8 import java.nio.ByteBuffer; 8 9 import java.nio.ByteOrder; 9 import java.nio. ShortBuffer;10 import java. nio.channels.FileChannel;10 import java.nio.file.Paths; 11 import java.util.Arrays; 11 12 import java.util.HashMap; 13 import java.util.List; 14 import java.util.Optional; 15 import java.util.regex.Matcher; 16 import java.util.regex.Pattern; 12 17 18 import org.apache.commons.compress.utils.IOUtils; 19 import org.openstreetmap.josm.data.Bounds; 13 20 import org.openstreetmap.josm.data.Preferences; 21 import org.openstreetmap.josm.data.coor.ILatLon; 14 22 import org.openstreetmap.josm.data.coor.LatLon; 23 import org.openstreetmap.josm.io.Compression; 15 24 import org.openstreetmap.josm.tools.CheckParameterUtil; 16 25 import org.openstreetmap.josm.tools.Logging; 17 26 … … import org.openstreetmap.josm.tools.Logging; 22 31 * @author Oliver Wieland <oliver.wieland@online.de> 23 32 */ 24 33 public class HgtReader { 25 private static final int SECONDS_PER_MINUTE = 60; 34 private static final int SRTM_EXTENT = 1; // degree 35 private static final List<String> COMPRESSION_EXT = Arrays.asList("xz", "gzip", "zip", "bz", "bz2"); 26 36 27 37 public static final String HGT_EXT = ".hgt"; 28 38 29 39 // alter these values for different SRTM resolutions 30 public static final int HGT_RES = 3; // resolution in arc seconds 31 public static final int HGT_ROW_LENGTH = 1201; // number of elevation values per line 32 public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file 40 public static final int HGT_VOID = Short.MIN_VALUE; // magic number which indicates 'void data' in HGT file 33 41 34 private final HashMap<String, ShortBuffer> cache = new HashMap<>();42 private static final HashMap<String, short[][]> cache = new HashMap<>(); 35 43 36 public double getElevationFromHgt(LatLon coor) {44 public static double getElevationFromHgt(ILatLon coor) { 37 45 try { 38 46 String file = getHgtFileName(coor); 39 47 // given area in cache? … … public class HgtReader { 47 55 for (String location : Preferences.getAllPossiblePreferenceDirs()) { 48 56 String fullPath = new File(location + File.separator + "elevation", file).getPath(); 49 57 File f = new File(fullPath); 58 if (!f.exists()) { 59 for (String ext : COMPRESSION_EXT) { 60 f = new File(fullPath + "." + ext); 61 if (f.exists()) break; 62 } 63 } 50 64 if (f.exists()) { 51 // found something: read HGT file... 52 ShortBuffer data = readHgtFile(fullPath); 53 // ... and store result in cache 54 cache.put(file, data); 65 read(f); 55 66 break; 56 67 } 57 68 } 58 69 } 59 70 60 71 // read elevation value 61 return readElevation(coor );72 return readElevation(coor, file); 62 73 } catch (FileNotFoundException e) { 63 74 Logging.error("Get elevation from HGT " + coor + " failed: => " + e.getMessage()); 64 75 // no problem... file not there … … public class HgtReader { 71 82 } 72 83 } 73 84 74 @SuppressWarnings("resource") 75 private ShortBuffer readHgtFile(String file) throws Exception { 76 CheckParameterUtil.ensureParameterNotNull(file); 85 public static Bounds read(File file) throws FileNotFoundException, IOException { 86 String location = file.getName(); 87 for (String ext : COMPRESSION_EXT) { 88 location = location.replaceAll("\\." + ext + "$", ""); 89 } 90 short[][] sb = readHgtFile(file.getPath()); 91 // Overwrite the cache file (assume that is desired) 92 cache.put(location, sb); 93 Pattern pattern = Pattern.compile("(N|S)([0-9]{2})(E|W)([0-9]{3})"); 94 Matcher matcher = pattern.matcher(location); 95 if (matcher.lookingAt()) { 96 int lat = (matcher.group(1) == "S" ? -1 : 1) * Integer.parseInt(matcher.group(2)); 97 int lon = (matcher.group(3) == "W" ? -1 : 1) * Integer.parseInt(matcher.group(4)); 98 return new Bounds(lat, lon, lat + 1, lon + 1); 99 } 100 return null; 101 } 77 102 78 FileChannel fc = null; 79 ShortBuffer sb = null; 80 try { 81 // Eclipse complains here about resource leak on 'fc' - even with 'finally' clause??? 82 fc = new FileInputStream(file).getChannel(); 83 // choose the right endianness 103 private static short[][] readHgtFile(String file) throws FileNotFoundException, IOException { 104 CheckParameterUtil.ensureParameterNotNull(file); 84 105 85 ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size()); 86 while (bb.remaining() > 0) fc.read(bb); 106 short[][] data = null; 87 107 88 bb.flip(); 89 sb = bb.order(ByteOrder.BIG_ENDIAN).asShortBuffer(); 90 } finally { 91 if (fc != null) fc.close(); 108 try (InputStream fis = Compression.getUncompressedFileInputStream(Paths.get(file))) { 109 // choose the right endianness 110 ByteBuffer bb = ByteBuffer.wrap(IOUtils.toByteArray(fis)); 111 //System.out.println(Arrays.toString(bb.array())); 112 bb.order(ByteOrder.BIG_ENDIAN); 113 int size = (int) Math.sqrt(bb.array().length / 2); 114 data = new short[size][size]; 115 int x = 0; 116 int y = 0; 117 while (x < size) { 118 while (y < size) { 119 data[x][y] = bb.getShort(2 * (x * size + y)); 120 y++; 121 } 122 x++; 123 y = 0; 124 } 92 125 } 93 126 94 return sb;127 return data; 95 128 } 96 129 97 130 /** … … public class HgtReader { 101 134 * @param coor the coordinate to get the elevation data for 102 135 * @return the elevation value or <code>Double.NaN</code>, if no value is present 103 136 */ 104 public double readElevation(LatLon coor) {137 public static double readElevation(LatLon coor) { 105 138 String tag = getHgtFileName(coor); 139 return readElevation(coor, tag); 140 } 141 142 /** 143 * Reads the elevation value for the given coordinate. 144 * 145 * See also <a href="http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file">stackexchange.com</a> 146 * @param coor the coordinate to get the elevation data for 147 * @param fileName The expected filename 148 * @return the elevation value or <code>Double.NaN</code>, if no value is present 149 */ 150 public static double readElevation(ILatLon coor, String fileName) { 106 151 107 ShortBuffer sb = cache.get(tag);152 short[][] sb = cache.get(fileName); 108 153 109 154 if (sb == null) { 110 155 return ElevationHelper.NO_ELEVATION; 111 156 } 112 157 113 // see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file 114 double fLat = frac(coor.lat()) * SECONDS_PER_MINUTE; 115 double fLon = frac(coor.lon()) * SECONDS_PER_MINUTE; 116 117 // compute offset within HGT file 118 int row = (int) Math.round(fLat * SECONDS_PER_MINUTE / HGT_RES); 119 int col = (int) Math.round(fLon * SECONDS_PER_MINUTE / HGT_RES); 120 121 row = HGT_ROW_LENGTH - row; 122 int cell = (HGT_ROW_LENGTH * (row - 1)) + col; 123 124 // valid position in buffer? 125 if (cell < sb.limit()) { 126 short ele = sb.get(cell); 127 // check for data voids 128 if (ele == HGT_VOID) { 129 return ElevationHelper.NO_ELEVATION; 130 } else { 131 return ele; 132 } 133 } else { 158 int[] index = getIndex(coor, sb.length); 159 short ele = sb[index[0]][index[1]]; 160 161 if (ele == HGT_VOID) { 134 162 return ElevationHelper.NO_ELEVATION; 135 163 } 164 return ele; 165 } 166 167 public static Optional<Bounds> getBounds(ILatLon location) { 168 final String fileName = getHgtFileName(location); 169 final short[][] sb = cache.get(fileName); 170 171 if (sb == null) { 172 return Optional.empty(); 173 } 174 175 final double latDegrees = location.lat(); 176 final double lonDegrees = location.lon(); 177 178 final float fraction = ((float) SRTM_EXTENT) / sb.length; 179 final int latitude = (int) Math.floor(latDegrees) + (latDegrees < 0 ? 1 : 0); 180 final int longitude = (int) Math.floor(lonDegrees) + (lonDegrees < 0 ? 1 : 0); 181 182 final int[] index = getIndex(location, sb.length); 183 final int latSign = latitude > 0 ? 1 : -1; 184 final int lonSign = longitude > 0 ? 1 : -1; 185 final double minLat = latitude + latSign * fraction * index[0]; 186 final double maxLat = latitude + latSign * fraction * (index[0] + 1); 187 final double minLon = longitude + lonSign * fraction * index[1]; 188 final double maxLon = longitude + lonSign * fraction * (index[1] + 1); 189 return Optional.of(new Bounds(Math.min(minLat, maxLat), Math.min(minLon, maxLon), 190 Math.max(minLat, maxLat), Math.max(minLon, maxLon))); 191 } 192 193 /** 194 * Get the index to use for a short[latitude][longitude] = height in meters array 195 * 196 * @param latLon 197 * The location to get the index for 198 * @param mapSize 199 * The size of the map 200 * @return A [latitude, longitude] = int (index) array. 201 */ 202 private static int[] getIndex(ILatLon latLon, int mapSize) 203 { 204 double latDegrees = latLon.lat(); 205 double lonDegrees = latLon.lon(); 206 207 float fraction = ((float) SRTM_EXTENT) / mapSize; 208 int latitude = (int) Math.floor(Math.abs(latDegrees - (int) latDegrees) / fraction); 209 int longitude = (int) Math.floor(Math.abs(lonDegrees - (int) lonDegrees) / fraction); 210 if (latDegrees >= 0) 211 { 212 latitude = mapSize - 1 - latitude; 213 } 214 if (lonDegrees < 0) 215 { 216 longitude = mapSize - 1 - longitude; 217 } 218 return new int[] { latitude, longitude }; 136 219 } 137 220 138 221 /** … … public class HgtReader { 143 226 * @param latLon the coordinate to get the filename for 144 227 * @return the file name of the HGT file 145 228 */ 146 public String getHgtFileName(LatLon latLon) {147 int lat = (int) latLon.lat();148 int lon = (int) latLon.lon();229 public static String getHgtFileName(ILatLon latLon) { 230 int lat = (int) Math.floor(latLon.lat()); 231 int lon = (int) Math.floor(latLon.lon()); 149 232 150 233 String latPref = "N"; 151 if (lat < 0) latPref = "S"; 234 if (lat < 0) { 235 latPref = "S"; 236 lat = Math.abs(lat); 237 } 152 238 153 239 String lonPref = "E"; 154 240 if (lon < 0) { 155 241 lonPref = "W"; 242 lon = Math.abs(lon); 156 243 } 157 244 158 return String.format("%s%02d%s%03d%s", latPref, lat, lonPref, lon, HGT_EXT);245 return latPref + lat + lonPref + lon + HGT_EXT; 159 246 } 160 247 161 248 public static double frac(double d) { … … public class HgtReader { 167 254 fPart = d - iPart; 168 255 return fPart; 169 256 } 257 258 public static void clearCache() { 259 cache.clear(); 260 } 170 261 } -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java index 44965bbd9..3b5718e90 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.elevation; 3 3 4 import java. util.Date;4 import java.time.Instant; 5 5 import java.util.List; 6 6 7 7 import org.openstreetmap.josm.data.Bounds; … … public interface IElevationProfile { 20 20 /** 21 21 * Gets the time stamp of first recorded track point. 22 22 */ 23 DategetStart();23 Instant getStart(); 24 24 25 25 /** 26 26 * Gets the time stamp of last recorded track point. 27 27 */ 28 DategetEnd();28 Instant getEnd(); 29 29 30 30 /** 31 31 * Gets the minimum elevation height of all tracks and routes. -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java index d77a46067..0a4e15988 100644
a b public class AddElevationLayerAction extends JosmAction { 27 27 if (currentLayer == null) { 28 28 currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name 29 29 MainApplication.getLayerManager().addLayer(currentLayer); 30 } else if (!MainApplication.getLayerManager().containsLayer(currentLayer)) { 31 currentLayer = null; 32 actionPerformed(arg0); 30 33 } 31 34 } 32 35 } -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java index 879a12dc2..69d015663 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.elevation.gpx; 3 3 4 import java.time.Instant; 4 5 import java.util.ArrayList; 5 import java.util.Date;6 6 import java.util.List; 7 7 8 8 import org.openstreetmap.josm.data.Bounds; … … IGpxWaypointVisitor { 44 44 private int maxHeight; 45 45 private int avrgHeight; 46 46 private double dist; 47 private Date start = new Date();48 private Date end = new Date();47 private Instant start; 48 private Instant end; 49 49 private final WayPoint[] importantWayPoints = new WayPoint[4]; 50 50 private IElevationProfile parent; 51 51 private int sumEle; // temp var for average height … … IGpxWaypointVisitor { 120 120 if (n == 0) 121 121 return; 122 122 123 start = new Date(0L);124 end = new Date();123 start = Instant.EPOCH; 124 end = Instant.now(); 125 125 this.minHeight = Integer.MAX_VALUE; 126 126 this.maxHeight = Integer.MIN_VALUE; 127 127 sumEle = 0; … … IGpxWaypointVisitor { 195 195 */ 196 196 protected void setStart(WayPoint wp) { 197 197 importantWayPoints[WAYPOINT_START] = wp; 198 if(wp.get Date() != null)199 this.start = wp.get Date();198 if(wp.getInstant() != null) 199 this.start = wp.getInstant(); 200 200 } 201 201 202 202 /** … … IGpxWaypointVisitor { 204 204 */ 205 205 protected void setEnd(WayPoint wp) { 206 206 importantWayPoints[WAYPOINT_END] = wp; 207 if(wp.get Date() != null)208 this.end = wp.get Date();207 if(wp.getInstant() != null) 208 this.end = wp.getInstant(); 209 209 } 210 210 211 211 public void setParent(IElevationProfile parent) { … … IGpxWaypointVisitor { 256 256 } 257 257 258 258 @Override 259 public DategetEnd() {259 public Instant getEnd() { 260 260 return end; 261 261 } 262 262 … … IGpxWaypointVisitor { 307 307 WayPoint wp2 = getEndWayPoint(); 308 308 309 309 if (wp1 != null && wp2 != null) { 310 Date wp1Date = wp1.getDate();311 Date wp2Date = wp2.getDate();310 Instant wp1Date = wp1.getInstant(); 311 Instant wp2Date = wp2.getInstant(); 312 312 if (wp1Date != null && wp2Date != null) { 313 return wp2Date. getTime() - wp1Date.getTime();313 return wp2Date.toEpochMilli() - wp1Date.toEpochMilli(); 314 314 } else { 315 315 Logging.warn("Waypoints without date: " + wp1 + " / " + wp2); 316 316 } … … IGpxWaypointVisitor { 325 325 } 326 326 327 327 @Override 328 public DategetStart() {328 public Instant getStart() { 329 329 return start; 330 330 } 331 331 … … IGpxWaypointVisitor { 389 389 return; 390 390 391 391 if (wp.hasDate()) { 392 if (wp.get Date().after(end)) {392 if (wp.getInstant().isAfter(this.end)) { 393 393 setEnd(wp); 394 394 } 395 395 396 if (wp.get Date().before(start)) {396 if (wp.getInstant().isBefore(start)) { 397 397 setStart(wp); 398 398 } 399 399 } -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java index ec63979ae..da76bf4c0 100644
a b import java.awt.Color; 7 7 import java.awt.Graphics; 8 8 import java.awt.Graphics2D; 9 9 import java.awt.Point; 10 import java.awt.Rectangle; 11 import java.awt.event.MouseEvent; 12 import java.awt.event.MouseListener; 10 13 11 14 import javax.swing.Action; 12 15 import javax.swing.Icon; 13 16 17 import org.apache.commons.jcs3.JCS; 14 18 import org.openstreetmap.gui.jmapviewer.MemoryTileCache; 15 19 import org.openstreetmap.gui.jmapviewer.Tile; 16 20 import org.openstreetmap.gui.jmapviewer.TileController; … … import org.openstreetmap.gui.jmapviewer.TileXY; 18 22 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 19 23 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 20 24 import org.openstreetmap.josm.data.Bounds; 25 import org.openstreetmap.josm.data.coor.ILatLon; 21 26 import org.openstreetmap.josm.data.coor.LatLon; 22 27 import org.openstreetmap.josm.data.imagery.CoordinateConversion; 28 import org.openstreetmap.josm.data.imagery.TileJobOptions; 29 import org.openstreetmap.josm.data.osm.BBox; 23 30 import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor; 31 import org.openstreetmap.josm.gui.MainApplication; 24 32 import org.openstreetmap.josm.gui.MapView; 33 import org.openstreetmap.josm.gui.Notification; 25 34 import org.openstreetmap.josm.gui.layer.Layer; 35 import org.openstreetmap.josm.gui.util.GuiHelper; 36 import org.openstreetmap.josm.plugins.elevation.ElevationHelper; 37 import org.openstreetmap.josm.plugins.elevation.HgtReader; 26 38 import org.openstreetmap.josm.plugins.elevation.IVertexRenderer; 27 39 import org.openstreetmap.josm.tools.ImageProvider; 28 40 import org.openstreetmap.josm.tools.Logging; … … import org.openstreetmap.josm.tools.Logging; 31 43 * @author Oliver Wieland <oliver.wieland@online.de> 32 44 * 33 45 */ 34 public class ElevationGridLayer extends Layer implements TileLoaderListener {46 public class ElevationGridLayer extends Layer implements TileLoaderListener, MouseListener { 35 47 private static final int ELE_ZOOM_LEVEL = 13; 36 48 private final IVertexRenderer vertexRenderer; 37 49 private final MemoryTileCache tileCache; … … public class ElevationGridLayer extends Layer implements TileLoaderListener { 39 51 protected ElevationGridTileLoader tileLoader; 40 52 protected TileController tileController; 41 53 54 private ILatLon clickLocation; 55 42 56 private Bounds lastBounds; 43 57 private TileSet tileSet; 44 58 45 59 public ElevationGridLayer(String name) { 46 60 super(name); 61 HgtReader.clearCache(); 62 MainApplication.getMap().mapView.addMouseListener(this); 47 63 48 64 setOpacity(0.8); 49 65 setBackgroundLayer(true); … … public class ElevationGridLayer extends Layer implements TileLoaderListener { 52 68 tileCache = new MemoryTileCache(); 53 69 tileCache.setCacheSize(500); 54 70 tileSource = new ElevationGridTileSource(name); 55 tileLoader = new ElevationGridTileLoader(this );71 tileLoader = new ElevationGridTileLoader(this, JCS.getInstance("elevationgridlayer"), new TileJobOptions(20, 20, null, 3600)); 56 72 tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader); 57 73 } 58 74 … … public class ElevationGridLayer extends Layer implements TileLoaderListener { 89 105 } 90 106 } 91 107 } 108 // Paint the current point area 109 ElevationHelper.getBounds(this.clickLocation).ifPresent(bounds -> { 110 final BBox bbox = bounds.toBBox(); 111 final Point upperLeft = mv.getPoint(bbox.getTopLeft()); 112 final Point bottomRight = mv.getPoint(bbox.getBottomRight()); 113 final Rectangle rectangle = new Rectangle(upperLeft.x, upperLeft.y, 114 bottomRight.x - upperLeft.x, bottomRight.y - upperLeft.y); 115 g.setColor(Color.RED); 116 g.draw(rectangle); 117 }); 92 118 } 93 119 94 120 @Override … … public class ElevationGridLayer extends Layer implements TileLoaderListener { 151 177 g.drawString(text, x, y); 152 178 } 153 179 180 @Override 181 public void mouseClicked(MouseEvent e) { 182 if (e.getButton() == MouseEvent.BUTTON1) { 183 this.clickLocation = MainApplication.getMap().mapView.getLatLon(e.getX(), e.getY()); 184 final double elevation = ElevationHelper.getSrtmElevation(clickLocation); 185 Notification notification = new Notification("Elevation is: " + elevation); 186 notification.setDuration(Notification.TIME_SHORT); 187 GuiHelper.runInEDT(notification::show); 188 GuiHelper.runInEDT(this::invalidate); 189 } 190 } 191 192 @Override 193 public void mousePressed(MouseEvent e) { 194 // Do nothing 195 } 196 197 @Override 198 public void mouseReleased(MouseEvent e) { 199 // Do nothing 200 } 201 202 @Override 203 public void mouseEntered(MouseEvent e) { 204 // Do nothing 205 } 206 207 @Override 208 public void mouseExited(MouseEvent e) { 209 // Do nothing 210 } 211 154 212 private class TileSet { 155 213 int x0, x1, y0, y1; 156 214 int tileMax = -1; … … public class ElevationGridLayer extends Layer implements TileLoaderListener { 223 281 return this.tilesSpanned() > 200; 224 282 } 225 283 } 284 285 @Override 286 public void destroy() { 287 super.destroy(); 288 HgtReader.clearCache(); 289 MainApplication.getMap().mapView.removeMouseListener(this); 290 } 226 291 } -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java index a21720fd4..390f17cc3 100644
a b import java.awt.Point; 9 9 import java.awt.image.BufferedImage; 10 10 import java.io.IOException; 11 11 import java.io.InputStream; 12 import java.util.List;13 12 import java.util.concurrent.BlockingDeque; 14 13 import java.util.concurrent.LinkedBlockingDeque; 15 14 … … public class ElevationGridTile extends Tile { 54 53 55 54 /** 56 55 * Paints the vertices of this tile. 57 * 58 * @param g the graphics context 56 * @param g the graphics context 59 57 * @param mv the map view 60 58 * @param vertexRenderer the vertex renderer 61 59 */ … … public class ElevationGridTile extends Tile { 66 64 Point p1 = mv.getPoint(eleVertex.get(1)); 67 65 Point p2 = mv.getPoint(eleVertex.get(2)); 68 66 Triangle shape = new Triangle(p0, p1, p2); 69 70 67 // obtain vertex color 71 68 g.setColor(vertexRenderer.getElevationColor(eleVertex)); 72 69 // TODO: Move to renderer … … public class ElevationGridTile extends Tile { 82 79 83 80 // We abuse the loadImage method to render the vertices... 84 81 // 85 while ( toDo.size() > 0) {82 while (!toDo.isEmpty()) { 86 83 EleVertex vertex = toDo.poll(); 87 84 88 85 if (vertex.isFinished()) { 89 86 vertices.add(vertex); 90 87 } else { 91 List<EleVertex> newV = vertex.divide(); 92 for (EleVertex eleVertex : newV) { 93 toDo.add(eleVertex); 94 } 88 toDo.addAll(vertex.divide()); 95 89 } 96 90 } 97 91 setLoaded(true); -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java index fccb15e1a..7bd5ef08b 100644
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.plugins.elevation.grid; 3 3 4 import java.io.IOException; 5 import java.net.URL; 6 import java.util.Optional; 7 import java.util.concurrent.ThreadPoolExecutor; 8 9 import org.apache.commons.jcs3.access.behavior.ICacheAccess; 4 10 import org.openstreetmap.gui.jmapviewer.Tile; 5 11 import org.openstreetmap.gui.jmapviewer.interfaces.TileJob; 6 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoader;7 12 import org.openstreetmap.gui.jmapviewer.interfaces.TileLoaderListener; 13 import org.openstreetmap.gui.jmapviewer.interfaces.TileSource; 14 import org.openstreetmap.josm.data.cache.BufferedImageCacheEntry; 15 import org.openstreetmap.josm.data.cache.JCSCachedTileLoaderJob; 16 import org.openstreetmap.josm.data.imagery.TMSCachedTileLoader; 17 import org.openstreetmap.josm.data.imagery.TileJobOptions; 8 18 import org.openstreetmap.josm.tools.CheckParameterUtil; 9 19 10 20 /** 11 21 * @author Olli 12 22 * 13 23 */ 14 public class ElevationGridTileLoader implements TileLoader { 15 protected TileLoaderListener listener; 24 public class ElevationGridTileLoader extends TMSCachedTileLoader { 16 25 17 public ElevationGridTileLoader(TileLoaderListener listener) { 18 CheckParameterUtil.ensureParameterNotNull(listener); 19 this.listener = listener; 20 } 26 class ElevationGridTileJob extends JCSCachedTileLoaderJob<String, BufferedImageCacheEntry> implements TileJob { 21 27 22 @Override23 public TileJob createTileLoaderJob(final Tile tile) {24 CheckParameterUtil.ensureParameterNotNull(tile);28 private final Tile tile; 29 private final TileLoaderListener listener; 30 private final ICacheAccess<String, BufferedImageCacheEntry> cache; 25 31 26 return new TileJob() { 27 28 @Override 29 public void run() { 30 synchronized (tile) { 31 if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading()) 32 return; 33 tile.initLoading(); 34 } 35 try { 36 tile.loadImage(null); 37 tile.setLoaded(true); 38 listener.tileLoadingFinished(tile, true); 39 } catch (Exception e) { 40 tile.setError(e.getMessage()); 41 listener.tileLoadingFinished(tile, false); 42 } finally { 43 tile.finishLoading(); 44 } 45 } 32 protected ElevationGridTileJob(TileLoaderListener listener, Tile tile, ICacheAccess<String, BufferedImageCacheEntry> cache, TileJobOptions options, 33 ThreadPoolExecutor downloadJobExecutor) { 34 super(cache, options, downloadJobExecutor); 35 this.cache = cache; 36 this.tile = tile; 37 this.listener = listener; 38 } 46 39 47 @Override 48 public void submit() { 49 run(); 40 @Override 41 public void run() { 42 synchronized (tile) { 43 if ((tile.isLoaded() && !tile.hasError()) || tile.isLoading()) 44 return; 45 tile.initLoading(); 46 } 47 try { 48 tile.loadImage(null); 49 tile.setLoaded(true); 50 listener.tileLoadingFinished(tile, true); 51 } catch (Exception e) { 52 tile.setError(e.getMessage()); 53 listener.tileLoadingFinished(tile, false); 54 } finally { 55 tile.finishLoading(); 50 56 } 57 } 58 59 @Override 60 public void submit() { 61 run(); 62 } 51 63 52 @Override 53 public void submit(boolean force) { 54 submit(); 64 @Override 65 public void submit(boolean force) { 66 submit(); 67 } 68 69 @Override 70 public String getCacheKey() { 71 if (tile != null) { 72 TileSource tileSource = tile.getTileSource(); 73 return Optional.ofNullable(tileSource.getName()).orElse("").replace(':', '_') + ':' 74 + tileSource.getTileId(tile.getZoom(), tile.getXtile(), tile.getYtile()); 55 75 } 56 }; 76 return null; 77 } 78 79 @Override 80 public URL getUrl() throws IOException { 81 return new URL(String.format("http://localhost/elevation/%d/%d", tile.getTileXY().getXIndex(), tile.getTileXY().getYIndex())); 82 } 83 84 @Override 85 protected BufferedImageCacheEntry createCacheEntry(byte[] content) { 86 return new BufferedImageCacheEntry(content); 87 } 88 } 89 90 /** 91 * Constructor 92 * @param listener called when tile loading has finished 93 * @param cache of the cache 94 * @param options tile job options 95 */ 96 public ElevationGridTileLoader(TileLoaderListener listener, ICacheAccess<String, BufferedImageCacheEntry> cache, 97 TileJobOptions options) { 98 super(listener, cache, options); 99 } 100 101 @Override 102 public TileJob createTileLoaderJob(final Tile tile) { 103 CheckParameterUtil.ensureParameterNotNull(tile); 104 105 return new ElevationGridTileJob(listener, 106 tile, 107 cache, 108 options, 109 getDownloadExecutor()); 57 110 } 58 111 59 112 @Override -
plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java
diff --git a/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java b/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java index 5d4dfd458..a45483432 100644
a b import java.awt.event.MouseEvent; 15 15 import java.awt.event.MouseMotionListener; 16 16 import java.text.Format; 17 17 import java.text.SimpleDateFormat; 18 import java.time.Instant; 18 19 import java.util.ArrayList; 19 import java.util.Date;20 20 import java.util.List; 21 21 22 22 import javax.swing.BorderFactory; … … public class ElevationProfilePanel extends JPanel implements ComponentListener, 253 253 /** 254 254 * Formats the date in a predefined manner: "21. Oct 2010, 12:10". 255 255 */ 256 private String formatDate( Datedate) {256 private String formatDate(Instant date) { 257 257 Format formatter = new SimpleDateFormat("d MMM yy, HH:mm"); 258 259 return formatter.format(date); 258 return formatter.format(date.toEpochMilli()); 260 259 } 261 260 262 261 /**
