Changeset 30344 in osm
- Timestamp:
- 2014-03-24T18:28:13+01:00 (11 years ago)
- Location:
- applications/editors/josm/plugins/ElevationProfile
- Files:
-
- 41 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/ElevationProfile/.settings/org.eclipse.jdt.ui.prefs
r29965 r30344 1 #Sat Jan 29 19:56:56 CET 20112 1 eclipse.preferences.version=1 3 2 editor_save_participant_org.eclipse.jdt.ui.postsavelistener.cleanup=true … … 39 38 sp_cleanup.remove_unnecessary_casts=true 40 39 sp_cleanup.remove_unnecessary_nls_tags=false 41 sp_cleanup.remove_unused_imports= false40 sp_cleanup.remove_unused_imports=true 42 41 sp_cleanup.remove_unused_local_variables=false 43 42 sp_cleanup.remove_unused_private_fields=true -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColorMap.java
r29977 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation; 15 3 … … 33 21 34 22 static { 35 23 colorMaps = new HashMap<String, ColorMap>(); 36 24 } 37 25 … … 41 29 42 30 public String getName() { 43 31 return name; 44 32 } 45 33 46 34 public void setName(String name) { 47 35 this.name = name; 48 36 } 49 37 … … 55 43 */ 56 44 public Color getColor(int elevation) { 57 58 59 60 45 // empty color map? 46 if (colorList == null || colorList.size() == 0) { 47 return Color.white; 48 } 61 49 62 63 64 65 50 // out of range? 51 if (elevation < colorList.get(0).ele) { 52 return colorList.get(0).getColor(); 53 } 66 54 67 68 69 70 55 int last = colorList.size() - 1; 56 if (elevation > colorList.get(last).ele) { 57 return colorList.get(last).getColor(); 58 } 71 59 72 73 74 75 60 // find elevation section 61 for (int i = 0; i < last; i++) { 62 ColorMapEntry e1 = colorList.get(i); 63 ColorMapEntry e2 = colorList.get(i + 1); 76 64 77 78 65 // elevation within range? 66 if (e1.getEle() <= elevation && e2.getEle() >= elevation) { 79 67 80 81 82 83 84 68 // interpolate color between both 69 double val = (elevation - e1.getEle()) / (double)(e2.getEle() - e1.getEle()); 70 return interpolate(e1.getColor(), e2.getColor(), val); 71 } 72 } 85 73 86 87 74 // here we should never end! 75 throw new RuntimeException("Inconsistent color map - found no entry for elevation " + elevation); 88 76 } 89 77 … … 96 84 */ 97 85 public static ColorMap getMap(String name) { 98 99 100 101 86 if (colorMaps.containsKey(name)) { 87 return colorMaps.get(name); 88 } 89 return null; 102 90 } 103 91 … … 108 96 */ 109 97 public static int size() { 110 98 return colorMaps != null ? colorMaps.size() : 0; 111 99 } 112 100 … … 119 107 */ 120 108 public static String[] getNames() { 121 109 return colorMaps.keySet().toArray(new String[size()]); 122 110 } 123 111 124 112 private static void registerColorMap(ColorMap newMap) { 125 126 113 CheckParameterUtil.ensureParameterNotNull(newMap); 114 colorMaps.put(newMap.getName(), newMap); 127 115 } 128 116 129 117 public static void unregisterColorMap(String name) { 130 131 132 118 if (colorMaps.containsKey(name)) { 119 colorMaps.remove(name); 120 } 133 121 } 134 122 135 123 public static Color interpolate(java.awt.Color c1, java.awt.Color c2, double ratio) { 136 137 138 139 140 124 double r1 = 1 -ratio; 125 // clip 126 if (r1 < 0) r1 = 0d; 127 if (r1 > 1) r1 = 1d; 128 double r2 = 1 - r1; 141 129 142 143 144 145 130 int r = (int) Math.round((r1 * c1.getRed()) + (r2 * c2.getRed())); 131 int g = (int) Math.round((r1 * c1.getGreen()) + (r2 * c2.getGreen())); 132 int b = (int) Math.round((r1 * c1.getBlue()) + (r2 * c2.getBlue())); 133 return new Color(r, g, b); 146 134 } 147 135 … … 156 144 */ 157 145 public static ColorMap create(String name, Color[] colors, int[] ele) { 158 159 146 CheckParameterUtil.ensureParameterNotNull(colors); 147 CheckParameterUtil.ensureParameterNotNull(ele); 160 148 161 162 163 149 if (colors.length != ele.length) { 150 throw new IllegalArgumentException("Arrays colors and ele must have same length: " + colors.length + " vs " + ele.length); 151 } 164 152 165 166 167 168 169 170 153 ColorMap map = new ColorMap(); 154 map.colorList = new ArrayList<ColorMap.ColorMapEntry>(); 155 map.name = name; 156 for (int i = 0; i < ele.length; i++) { 157 map.colorList.add(map.new ColorMapEntry(colors[i], ele[i])); 158 } 171 159 172 173 160 // sort by elevation 161 Collections.sort(map.colorList); 174 162 175 176 163 registerColorMap(map); 164 return map; 177 165 } 178 166 179 167 180 168 class ColorMapEntry implements Comparable<ColorMapEntry> { 181 182 169 private final int ele; // limit 170 private final Color color; 183 171 184 185 186 187 188 172 public ColorMapEntry(Color color, int ele) { 173 super(); 174 this.color = color; 175 this.ele = ele; 176 } 189 177 190 191 192 178 public int getEle() { 179 return ele; 180 } 193 181 194 195 196 182 public Color getColor() { 183 return color; 184 } 197 185 198 199 200 201 186 @Override 187 public int compareTo(ColorMapEntry o) { 188 return this.ele - o.ele; 189 } 202 190 } 203 191 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java
r29982 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 36 23 /* Countries which use the imperial system instead of the metric system. */ 37 24 private static String IMPERIAL_SYSTEM_COUNTRIES[] = { 38 "en_US",/* USA */39 "en_CA",/* Canada */40 "en_AU",/* Australia */41 "en_NZ",/* New Zealand */42 // "de_DE",/* for testing only */43 "en_ZA"/* South Africa */25 "en_US", /* USA */ 26 "en_CA", /* Canada */ 27 "en_AU", /* Australia */ 28 "en_NZ", /* New Zealand */ 29 // "de_DE", /* for testing only */ 30 "en_ZA" /* South Africa */ 44 31 }; 45 32 … … 64 51 */ 65 52 public static GeoidCorrectionKind getGeoidKind() { 66 53 return geoidKind; 67 54 } 68 55 69 56 public static void setGeoidKind(GeoidCorrectionKind geoidKind) { 70 57 ElevationHelper.geoidKind = geoidKind; 71 58 } 72 59 … … 76 63 */ 77 64 public static UnitMode getUnitMode() { 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 65 //TODO: Use this until /JOSM/src/org/openstreetmap/josm/gui/NavigatableComponent.java 66 // has a an appropriate method 67 68 // unit mode already determined? 69 if (unitMode != UnitMode.NotSelected) { 70 return unitMode; 71 } 72 73 // Set default 74 unitMode = UnitMode.Metric; 75 76 // Check if user could prefer imperial system 77 Locale l = Locale.getDefault(); 78 for (int i = 0; i < IMPERIAL_SYSTEM_COUNTRIES.length; i++) { 79 String ctry = l.toString(); 80 if (IMPERIAL_SYSTEM_COUNTRIES[i].equals(ctry)) { 81 unitMode = UnitMode.Imperial; 82 } 83 } 84 85 return unitMode; 99 86 } 100 87 … … 104 91 */ 105 92 public static String getUnit() { 106 107 108 109 110 111 112 113 93 switch (getUnitMode()) { 94 case Metric: 95 return "m"; 96 case Imperial: 97 return "ft"; 98 default: 99 throw new RuntimeException("Invalid or unsupported unit mode: " + unitMode); 100 } 114 101 } 115 102 … … 121 108 */ 122 109 public static boolean isValidElevation(double ele) { 123 110 return !Double.isNaN(ele); 124 111 } 125 112 … … 134 121 */ 135 122 public static double getElevation(WayPoint wpt) { 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 123 if (wpt == null) return NO_ELEVATION; 124 125 // try to get elevation from HGT file 126 double eleInt = getSrtmElevation(wpt.getCoor()); 127 if (isValidElevation(eleInt)) { 128 return convert(eleInt); 129 } 130 131 // no HGT, check for elevation data in GPX 132 if (!wpt.attr.containsKey(HEIGHT_ATTRIBUTE)) { 133 // GPX has no elevation data :-( 134 return NO_ELEVATION; 135 } 136 137 // Parse elevation from GPX data 138 String height = wpt.getString(ElevationHelper.HEIGHT_ATTRIBUTE); 139 try { 140 double z = Double.parseDouble(height); 141 142 return convert(z); 143 } catch (NumberFormatException e) { 144 System.err.println(String.format( 145 "Cannot parse double from '%s': %s", height, e 146 .getMessage())); 147 return NO_ELEVATION; 148 } 162 149 } 163 150 164 151 165 152 private static double getElevation(LatLon ll) { 166 167 168 153 double ele = getSrtmElevation(ll); 154 //System.out.println("Get elevation " + ll + " => " + ele); 155 return convert(ele); 169 156 } 170 157 … … 176 163 */ 177 164 private static double convert(double ele) { 178 179 180 181 182 183 184 185 186 187 165 if (isValidElevation(ele)) { 166 if (getUnitMode() == UnitMode.Imperial) { 167 // translate to feet 168 return meter2Feet(ele); 169 } else { 170 // keep 'as is' 171 return ele; 172 } 173 } 174 return NO_ELEVATION; 188 175 } 189 176 … … 197 184 */ 198 185 public static double computeSlope(LatLon w1, LatLon w2) { 199 200 201 202 203 204 205 206 207 208 209 210 211 186 // same coordinates? -> return 0, if yes 187 if (w1.equals(w2)) return 0; 188 189 // get distance in meters and divide it by 100 in advance 190 double distInMeter = convert(w1.greatCircleDistance(w2) / 100.0); 191 192 // get elevation (difference) - is converted automatically to feet 193 int ele1 = (int) ElevationHelper.getElevation(w1); 194 int ele2 = (int) ElevationHelper.getElevation(w2); 195 int dH = ele2 - ele1; 196 197 // Slope in percent is define as elevation gain/loss in meters related to a distance of 100m 198 return dH / distInMeter; 212 199 } 213 200 … … 219 206 */ 220 207 public static double meter2Feet(double meter) { 221 208 return meter * METER_TO_FEET; 222 209 } 223 210 … … 228 215 */ 229 216 public static String getElevationText(int elevation) { 230 217 return String.format("%d %s", elevation, getUnit()); 231 218 } 232 219 … … 237 224 */ 238 225 public static String getElevationText(double elevation) { 239 226 return String.format("%d %s", (int)Math.round(elevation), getUnit()); 240 227 } 241 228 … … 247 234 */ 248 235 public static String getElevationText(WayPoint wpt) { 249 250 251 252 236 if (wpt == null) return "-"; 237 238 int elevation = (int)Math.round(ElevationHelper.getElevation(wpt)); 239 return String.format("%d %s", elevation, getUnit()); 253 240 } 254 241 … … 259 246 */ 260 247 public static String getTimeText(WayPoint wpt) { 261 262 263 264 265 248 if (wpt == null) return null; 249 250 int hour = ElevationHelper.getHourOfWayPoint(wpt); 251 int min = ElevationHelper.getMinuteOfWayPoint(wpt); 252 return String.format("%02d:%02d", hour, min); 266 253 } 267 254 … … 275 262 */ 276 263 public static double getSrtmElevation(LatLon ll) { 277 278 279 280 281 282 283 284 285 286 287 264 if (ll != null) { 265 // Try to read data from SRTM file 266 // TODO: Option to switch this off 267 double eleHgt = hgt.getElevationFromHgt(ll); 268 269 //System.out.println("Get elevation from HGT " + ll + " => " + eleHgt); 270 if (isValidElevation(eleHgt)) { 271 return eleHgt; 272 } 273 } 274 return NO_ELEVATION; 288 275 } 289 276 … … 295 282 */ 296 283 public static boolean hasSrtmData(Bounds bounds) { 297 298 299 300 301 302 returnisValidElevation(getSrtmElevation(tl)) &&303 284 if (bounds == null) return false; 285 286 LatLon tl = bounds.getMin(); 287 LatLon br = bounds.getMax(); 288 289 return isValidElevation(getSrtmElevation(tl)) && 290 isValidElevation(getSrtmElevation(br)); 304 291 } 305 292 … … 309 296 */ 310 297 public static byte getGeoidCorrection(WayPoint wpt) { 311 312 313 314 315 316 317 318 319 298 /* 299 int lat = (int)Math.round(wpt.getCoor().lat()); 300 int lon = (int)Math.round(wpt.getCoor().lon()); 301 byte geoid = GeoidData.getGeoid(lat, lon); 302 303 System.out.println( 304 String.format("Geoid(%d, %d) = %d", lat, lon, geoid)); 305 */ 306 return 0; 320 307 } 321 308 … … 332 319 */ 333 320 public static List<WayPoint> downsampleWayPoints(List<WayPoint> origList, 334 335 336 337 338 339 340 341 342 343 344 345 346 347 348 349 350 351 352 353 321 int targetSize) { 322 if (origList == null) 323 return null; 324 if (targetSize <= 0) 325 throw new IllegalArgumentException( 326 "targetSize must be greater than zero"); 327 328 int origSize = origList.size(); 329 if (origSize <= targetSize) { 330 return origList; 331 } 332 333 int delta = (int) Math.max(Math.ceil(origSize / targetSize), 2); 334 335 List<WayPoint> res = new ArrayList<WayPoint>(targetSize); 336 for (int i = 0; i < origSize; i += delta) { 337 res.add(origList.get(i)); 338 } 339 340 return res; 354 341 } 355 342 … … 360 347 */ 361 348 public static int getHourOfWayPoint(WayPoint wpt) { 362 363 364 365 366 349 if (wpt == null) return -1; 350 351 Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance 352 calendar.setTime(wpt.getTime()); // assigns calendar to given date 353 return calendar.get(Calendar.HOUR_OF_DAY); 367 354 } 368 355 … … 373 360 */ 374 361 public static int getMinuteOfWayPoint(WayPoint wpt) { 375 376 377 378 379 362 if (wpt == null) return -1; 363 364 Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance 365 calendar.setTime(wpt.getTime()); // assigns calendar to given date 366 return calendar.get(Calendar.MINUTE); 380 367 } 381 368 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationMapMode.java
r29955 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 27 14 */ 28 15 public class ElevationMapMode extends MapMode implements IElevationModelListener { 29 /** 30 * 31 */ 32 private static final long serialVersionUID = -1011179566962655639L; 33 16 /** 17 * 18 */ 19 private static final long serialVersionUID = -1011179566962655639L; 34 20 35 public ElevationMapMode(String name, MapFrame mapFrame) {36 super(name,37 "elevation.png",38 tr("Shows elevation profile"),39 mapFrame,40 Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));41 }42 21 43 /* (non-Javadoc) 44 * @see org.openstreetmap.josm.plugins.elevation.IElevationModelListener#elevationProfileChanged(org.openstreetmap.josm.plugins.elevation.IElevationProfile) 45 */ 46 public void elevationProfileChanged(IElevationProfile profile) { 47 ElevationProfilePlugin.getCurrentLayer().setProfile(profile); 48 } 22 public ElevationMapMode(String name, MapFrame mapFrame) { 23 super(name, 24 "elevation.png", 25 tr("Shows elevation profile"), 26 mapFrame, 27 Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR)); 28 } 49 29 50 @Override 51 public void enterMode() { 52 super.enterMode(); 53 ElevationProfilePlugin.getCurrentLayer().setVisible(true); 54 } 30 @Override 31 public void elevationProfileChanged(IElevationProfile profile) { 32 ElevationProfilePlugin.getCurrentLayer().setProfile(profile); 33 } 55 34 56 @Override 57 public void exitMode() { 58 super.exitMode(); 59 ElevationProfilePlugin.getCurrentLayer().setVisible(false); 60 } 35 @Override 36 public void enterMode() { 37 super.enterMode(); 38 ElevationProfilePlugin.getCurrentLayer().setVisible(true); 39 } 40 41 @Override 42 public void exitMode() { 43 super.exitMode(); 44 ElevationProfilePlugin.getCurrentLayer().setVisible(false); 45 } 61 46 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 46 33 */ 47 34 public ElevationProfilePlugin(PluginInformation info) { 48 35 super(info); 49 36 50 51 52 53 54 55 56 57 58 59 60 61 62 63 37 try { 38 eleMode = new ElevationMapMode("Elevation profile", Main.map); 39 eleModeButton = new IconToggleButton(eleMode); 40 41 JosmAction action = new AddElevationLayerAction(); 42 43 createColorMaps(); 44 45 // TODO: Disable this view as long as it is not stable 46 MainMenu.add(Main.main.menu.imagerySubMenu, action, false, 0); 47 } catch (Exception e1) { 48 System.err.println("Init of ElevationProfilePlugin failed: " + e1); 49 e1.printStackTrace(); 50 } 64 51 } 65 52 … … 69 56 * an alternative Painter. 70 57 */ 71 @Override 58 @Override 72 59 public void mapFrameInitialized(MapFrame oldFrame, MapFrame newFrame) { 73 60 super.mapFrameInitialized(oldFrame, newFrame); 74 61 75 76 77 78 79 80 81 62 if (newFrame != null) { 63 newFrame.addMapMode(eleModeButton); 64 ElevationProfileDialog eleProfileDlg = new ElevationProfileDialog(); 65 eleProfileDlg.addModelListener(eleMode); 66 eleProfileDlg.setProfileLayer(getCurrentLayer()); 67 newFrame.addToggleDialog(eleProfileDlg); 68 } 82 69 } 83 70 … … 88 75 */ 89 76 public static ElevationProfileLayer getCurrentLayer(){ 90 91 92 Main.main.addLayer(currentLayer); 93 94 77 if(currentLayer == null){ 78 currentLayer = new ElevationProfileLayer(tr("Elevation Profile")); 79 Main.main.addLayer(currentLayer); 80 } 81 return currentLayer; 95 82 } 96 83 97 84 private void createColorMaps() { 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 }, 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 3000 148 149 85 // Data taken from http://proceedings.esri.com/library/userconf/proc98/proceed/to850/pap842/p842.htm 86 ColorMap.create("Physical_US", 87 new Color[]{ 88 new Color(18,129,242), 89 new Color(113,153,89), 90 new Color(117,170,101), 91 new Color(149,190,113), 92 new Color(178,214,117), 93 new Color(202,226,149), 94 new Color(222,238,161), 95 new Color(242,238,161), 96 new Color(238,222,153), 97 new Color(242,206,133), 98 new Color(234,182,129), 99 new Color(218,157,121), 100 new Color(194,141,125), 101 new Color(214,157,145), 102 new Color(226,174,165), 103 new Color(222,186,182), 104 new Color(238,198,210), 105 new Color(255,206,226), 106 new Color(250,218,234), 107 new Color(255,222,230), 108 new Color(255,230,242), 109 new Color(255,242,255) 110 }, 111 // elevation in meters - the page above uses feet, so these values differs slightly 112 new int[]{ 113 -3000, 114 0, 115 150, 116 300, 117 450, 118 600, 119 750, 120 900, 121 1050, 122 1200, 123 1350, 124 1500, 125 1650, 126 1800, 127 1950, 128 2100, 129 2250, 130 2400, 131 2550, 132 2700, 133 2750, 134 3000 135 } 136 ); 150 137 } 151 138 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation; 15 3 … … 27 15 import org.openstreetmap.josm.tools.CheckParameterUtil; 28 16 29 30 17 /** 31 18 * Class HgtReader reads data from SRTM HGT files. Currently this class is restricted to a resolution of 3 arc seconds. 32 * 19 * 33 20 * SRTM data files are available at the <a href="http://dds.cr.usgs.gov/srtm/version2_1/SRTM3">NASA SRTM site</a> 34 21 * @author Oliver Wieland <oliver.wieland@online.de> … … 38 25 39 26 public static final String HGT_EXT = ".hgt"; 40 27 41 28 // alter these values for different SRTM resolutions 42 29 public static final int HGT_RES = 3; // resolution in arc seconds 43 30 public static final int HGT_ROW_LENGTH = 1201; // number of elevation values per line 44 31 public static final int HGT_VOID = -32768; // magic number which indicates 'void data' in HGT file 45 46 private HashMap<String, ShortBuffer> cache = new HashMap<String, ShortBuffer>();47 32 33 private final HashMap<String, ShortBuffer> cache = new HashMap<String, ShortBuffer>(); 34 48 35 public double getElevationFromHgt(LatLon coor) { 49 50 51 52 53 54 55 56 57 58 59 for (String location : Main.pref.getAllPossiblePreferenceDirs()) { 60 61 62 63 64 ShortBuffer data = readHgtFile(fullPath);65 66 67 68 69 70 } 71 72 73 74 75 76 77 78 79 80 ioe.printStackTrace(System.err); 81 82 return ElevationHelper.NO_ELEVATION; 83 } 36 try { 37 String file = getHgtFileName(coor); 38 // given area in cache? 39 if (!cache.containsKey(file)) { 40 41 // fill initial cache value. If no file is found, then 42 // we use it as a marker to indicate 'file has been searched 43 // but is not there' 44 cache.put(file, null); 45 // Try all resource directories 46 for (String location : Main.pref.getAllPossiblePreferenceDirs()) { 47 String fullPath = new File(location + File.separator + "elevation", file).getPath(); 48 File f = new File(fullPath); 49 if (f.exists()) { 50 // found something: read HGT file... 51 ShortBuffer data = readHgtFile(fullPath); 52 // ... and store result in cache 53 cache.put(file, data); 54 break; 55 } 56 } 57 } 58 59 // read elevation value 60 return readElevation(coor); 61 } catch (FileNotFoundException e) { 62 System.err.println("Get elevation from HGT " + coor + " failed: => " + e.getMessage()); 63 // no problem... file not there 64 return ElevationHelper.NO_ELEVATION; 65 } catch (Exception ioe) { 66 // oops... 67 ioe.printStackTrace(System.err); 68 // fallback 69 return ElevationHelper.NO_ELEVATION; 70 } 84 71 } 85 72 86 73 @SuppressWarnings("resource") 87 74 private ShortBuffer readHgtFile(String file) throws Exception { 88 75 CheckParameterUtil.ensureParameterNotNull(file); 89 76 90 91 92 try { 93 94 95 96 97 98 99 100 101 //sb = bb.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); 102 103 104 105 106 107 return sb; 77 FileChannel fc = null; 78 ShortBuffer sb = null; 79 try { 80 // Eclipse complains here about resource leak on 'fc' - even with 'finally' clause??? 81 fc = new FileInputStream(file).getChannel(); 82 // choose the right endianness 83 84 ByteBuffer bb = ByteBuffer.allocateDirect((int) fc.size()); 85 while (bb.remaining() > 0) fc.read(bb); 86 87 bb.flip(); 88 //sb = bb.order(ByteOrder.LITTLE_ENDIAN).asShortBuffer(); 89 sb = bb.order(ByteOrder.BIG_ENDIAN).asShortBuffer(); 90 } finally { 91 if (fc != null) fc.close(); 92 } 93 94 return sb; 108 95 } 109 96 110 97 /** 111 98 * Reads the elevation value for the given coordinate. … … 116 103 */ 117 104 public double readElevation(LatLon coor) { 118 String tag = getHgtFileName(coor); 119 120 ShortBuffer sb = cache.get(tag); 121 122 if (sb == null) { 123 return ElevationHelper.NO_ELEVATION; 124 } 125 126 // see http://gis.stackexchange.com/questions/43743/how-to-extract-elevation-from-hgt-file 127 double fLat = frac(coor.lat()) * SECONDS_PER_MINUTE; 128 double fLon = frac(coor.lon()) * SECONDS_PER_MINUTE; 129 130 // compute offset within HGT file 131 int row = (int)Math.round(fLat * SECONDS_PER_MINUTE / HGT_RES); 132 int col = (int)Math.round(fLon * SECONDS_PER_MINUTE / HGT_RES); 133 134 row = HGT_ROW_LENGTH - row; 135 int cell = (HGT_ROW_LENGTH* (row - 1)) + col; 136 137 //System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit()); 105 String tag = getHgtFileName(coor); 138 106 139 // valid position in buffer? 140 if (cell < sb.limit()) { 141 short ele = sb.get(cell); 142 //System.out.println("==> Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + " = " + ele); 143 // check for data voids 144 if (ele == HGT_VOID) { 145 return ElevationHelper.NO_ELEVATION; 146 } else { 147 return ele; 148 } 149 } else { 150 return ElevationHelper.NO_ELEVATION; 151 } 107 ShortBuffer sb = cache.get(tag); 108 109 if (sb == null) { 110 return ElevationHelper.NO_ELEVATION; 111 } 112 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 //System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit()); 125 126 // valid position in buffer? 127 if (cell < sb.limit()) { 128 short ele = sb.get(cell); 129 //System.out.println("==> Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + " = " + ele); 130 // check for data voids 131 if (ele == HGT_VOID) { 132 return ElevationHelper.NO_ELEVATION; 133 } else { 134 return ele; 135 } 136 } else { 137 return ElevationHelper.NO_ELEVATION; 138 } 152 139 } 153 140 154 141 /** 155 142 * Gets the associated HGT file name for the given way point. Usually the … … 161 148 */ 162 149 public String getHgtFileName(LatLon latLon) { 163 164 165 166 167 168 169 170 171 172 173 174 150 int lat = (int) latLon.lat(); 151 int lon = (int) latLon.lon(); 152 153 String latPref = "N"; 154 if (lat < 0) latPref = "S"; 155 156 String lonPref = "E"; 157 if (lon < 0) { 158 lonPref = "W"; 159 } 160 161 return String.format("%s%02d%s%03d%s", latPref, lat, lonPref, lon, HGT_EXT); 175 162 } 176 163 177 164 public static double frac(double d) { 178 179 165 long iPart; 166 double fPart; 180 167 181 182 183 184 168 // Get user input 169 iPart = (long) d; 170 fPart = d - iPart; 171 return fPart; 185 172 } 186 173 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IEleRenderingListener.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation; 15 3 … … 17 5 18 6 public interface IEleRenderingListener { 19 7 20 8 /** 21 9 * Notifies client that an elevation vertex has been finished for rendering. … … 24 12 */ 25 13 public void finished(EleVertex vertex); 26 14 27 15 /** 28 16 * Notifies a client that all vertices can be rendered now. -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationModel.java
r29955 r30344 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.plugins.elevation; 2 3 3 4 import java.util.List; 4 5 5 6 6 public interface IElevationModel { … … 33 33 */ 34 34 public abstract List<IElevationProfile> getProfiles(); 35 35 36 36 /** 37 37 * Gets the current profile. … … 40 40 */ 41 41 public abstract IElevationProfile getCurrentProfile(); 42 42 43 43 /** 44 44 * Sets the current profile. … … 47 47 */ 48 48 public abstract void setCurrentProfile(IElevationProfile newProfile); 49 49 50 50 /** 51 51 * Sets the current profile by index. … … 54 54 */ 55 55 public abstract void setCurrentProfile(int index); 56 56 57 57 /** 58 58 * Gets the number of elevation profiles within the model. -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationModelListener.java
r29955 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 18 5 19 6 /** 20 * This interface is intended to allow clients reaction on changes in the elevation model changes (e. g. 7 * This interface is intended to allow clients reaction on changes in the elevation model changes (e. g. 21 8 * repaint UI widgets). 22 9 * {@link ElevationModel} … … 24 11 */ 25 12 public interface IElevationModelListener { 26 27 28 29 30 13 /** 14 * Notifies listeners that the selected track has been changed. 15 * @param model The model changed. 16 */ 17 void elevationProfileChanged(IElevationProfile model); 31 18 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationProfile.java
r29961 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 26 13 */ 27 14 public interface IElevationProfile { 28 /** 29 * Gets the name of the elevation profile. 30 * @return 31 */ 32 public abstract String getName(); 33 34 /** 35 * Gets the time stamp of first recorded track point. 36 * @return 37 */ 38 public abstract Date getStart(); 15 /** 16 * Gets the name of the elevation profile. 17 * @return 18 */ 19 public abstract String getName(); 39 20 40 /** 41 * Gets the time stamp of last recorded track point. 42 * @return 43 */ 44 public abstract Date getEnd(); 45 46 /** 47 * Gets the minimum elevation height of all tracks and routes. 48 * @return 49 */ 50 public abstract int getMinHeight(); 21 /** 22 * Gets the time stamp of first recorded track point. 23 * @return 24 */ 25 public abstract Date getStart(); 51 26 52 /** 53 * Gets the maximum elevation height of all tracks and routes. 54 * @return 55 */ 56 public abstract int getMaxHeight(); 57 58 /** 59 * Gets the distance of the track in kilometers. 60 */ 61 public abstract double getDistance(); 62 63 /** 64 * Gets the average elevation height of all tracks and routes. 65 * @return 66 */ 67 public abstract int getAverageHeight(); 68 69 /** 70 * Gets the difference between min and max elevation. 71 * @return 72 */ 73 public int getHeightDifference(); 74 75 /** 76 * Gets the elevation gain. 77 * 78 * @return 79 */ 80 public int getGain(); 27 /** 28 * Gets the time stamp of last recorded track point. 29 * @return 30 */ 31 public abstract Date getEnd(); 81 32 82 /** 83 * Gets the total number of way points (sum of all way points of all tracks and routes). 84 * @return 85 */ 86 public abstract int getNumberOfWayPoints(); 87 88 /** 89 * Gets the list containing the way points. 90 * @return 91 */ 92 public List<WayPoint> getWayPoints(); 93 94 /** 95 * Gets the first recorded way point. 96 * @return 97 */ 98 public WayPoint getStartWayPoint(); 99 100 /** 101 * Gets the last recorded way point. 102 * @return 103 */ 104 public WayPoint getEndWayPoint(); 105 106 /** 107 * Gets the way point with the highest elevation value. 108 * @return 109 */ 110 public WayPoint getMaxWayPoint(); 111 112 /** 113 * Gets the way point with the lowest elevation value. 114 * @return 115 */ 116 public WayPoint getMinWayPoint(); 117 118 /** 119 * Gets a flag indicating whether the associated way points 120 * contained elevation data or not. This is the case if min 121 * and max height are equal. 122 * @return 123 */ 124 public boolean hasElevationData(); 33 /** 34 * Gets the minimum elevation height of all tracks and routes. 35 * @return 36 */ 37 public abstract int getMinHeight(); 125 38 126 /** 127 * Returns the time between start and end of the track. 128 * @return 129 */ 130 public long getTimeDifference(); 131 132 /** 133 * Gets the elevation value for at the given data index point. 134 */ 135 public int elevationValueAt(int i); 136 137 /** 138 * Gets the coordinate bounds of the elevation profile. 139 * 140 * @return the bounds 141 */ 142 public Bounds getBounds(); 143 144 /** 145 * Gets the children of the segment (maybe null). 146 */ 147 public List<IElevationProfile> getChildren(); 148 149 /** 150 * Gets the parent of the elevation profile. 151 */ 152 public IElevationProfile getParent(); 153 154 /** 155 * Triggers model refresh. 156 */ 157 public void updateElevationData(); 39 /** 40 * Gets the maximum elevation height of all tracks and routes. 41 * @return 42 */ 43 public abstract int getMaxHeight(); 44 45 /** 46 * Gets the distance of the track in kilometers. 47 */ 48 public abstract double getDistance(); 49 50 /** 51 * Gets the average elevation height of all tracks and routes. 52 * @return 53 */ 54 public abstract int getAverageHeight(); 55 56 /** 57 * Gets the difference between min and max elevation. 58 * @return 59 */ 60 public int getHeightDifference(); 61 62 /** 63 * Gets the elevation gain. 64 * 65 * @return 66 */ 67 public int getGain(); 68 69 /** 70 * Gets the total number of way points (sum of all way points of all tracks and routes). 71 * @return 72 */ 73 public abstract int getNumberOfWayPoints(); 74 75 /** 76 * Gets the list containing the way points. 77 * @return 78 */ 79 public List<WayPoint> getWayPoints(); 80 81 /** 82 * Gets the first recorded way point. 83 * @return 84 */ 85 public WayPoint getStartWayPoint(); 86 87 /** 88 * Gets the last recorded way point. 89 * @return 90 */ 91 public WayPoint getEndWayPoint(); 92 93 /** 94 * Gets the way point with the highest elevation value. 95 * @return 96 */ 97 public WayPoint getMaxWayPoint(); 98 99 /** 100 * Gets the way point with the lowest elevation value. 101 * @return 102 */ 103 public WayPoint getMinWayPoint(); 104 105 /** 106 * Gets a flag indicating whether the associated way points 107 * contained elevation data or not. This is the case if min 108 * and max height are equal. 109 * @return 110 */ 111 public boolean hasElevationData(); 112 113 /** 114 * Returns the time between start and end of the track. 115 * @return 116 */ 117 public long getTimeDifference(); 118 119 /** 120 * Gets the elevation value for at the given data index point. 121 */ 122 public int elevationValueAt(int i); 123 124 /** 125 * Gets the coordinate bounds of the elevation profile. 126 * 127 * @return the bounds 128 */ 129 public Bounds getBounds(); 130 131 /** 132 * Gets the children of the segment (maybe null). 133 */ 134 public List<IElevationProfile> getChildren(); 135 136 /** 137 * Gets the parent of the elevation profile. 138 */ 139 public IElevationProfile getParent(); 140 141 /** 142 * Triggers model refresh. 143 */ 144 public void updateElevationData(); 158 145 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IVertexRenderer.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation; 15 3 … … 24 12 */ 25 13 public interface IVertexRenderer { 26 14 27 15 /** 28 16 * Gets the color according to the given elevation. … … 32 20 */ 33 21 public Color getElevationColor(EleVertex vertex); 34 22 35 23 /** 36 24 * Selects color map with the given name. If no … … 40 28 */ 41 29 public void selectColorMap(String name); 42 30 43 31 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/UnitMode.java
r23795 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation; 16 3 … … 20 7 */ 21 8 public enum UnitMode { 22 23 24 25 // Chinese system missing 9 NotSelected, 10 Metric, 11 Imperial 12 // Chinese system missing 26 13 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java
r29977 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation.actions; 15 3 … … 25 13 public class AddElevationLayerAction extends JosmAction { 26 14 27 28 29 30 31 15 /** 16 * 17 */ 18 private static final long serialVersionUID = -745642875640041385L; 19 private Layer currentLayer; 32 20 33 public AddElevationLayerAction() { 34 super(tr("Elevation Grid Layer (experimental!)"), "elevation", tr("Shows elevation grid layer"), null, true); 35 } 36 37 @Override 38 public void actionPerformed(ActionEvent arg0) { 39 if (currentLayer == null) { 40 currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name 41 Main.main.addLayer(currentLayer); 21 public AddElevationLayerAction() { 22 super(tr("Elevation Grid Layer (experimental!)"), "elevation", tr("Shows elevation grid layer"), null, true); 42 23 } 43 24 44 } 45 25 @Override 26 public void actionPerformed(ActionEvent arg0) { 27 if (currentLayer == null) { 28 currentLayer = new ElevationGridLayer(tr("Elevation Grid")); // TODO: Better name 29 Main.main.addLayer(currentLayer); 30 } 31 } 46 32 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 37 24 */ 38 25 public class ElevationModel implements IGpxVisitor, IElevationModel { 39 // private int sliceSize; 40 private int trackCounter; 41 private GpxData gpxData; 42 private String name; 43 private WayPointMap profiles = new WayPointMap(); 44 private List<IElevationModelListener> listeners = new ArrayList<IElevationModelListener>(); 45 private List<WayPoint> buffer = new ArrayList<WayPoint>(); 46 private int currentProfileIndex = 0; 47 private ElevationProfile curProfile = null; 48 49 /** 50 * Instantiates a new elevation model. 51 */ 52 public ElevationModel() { 53 this("", null); 54 } 55 56 /** 57 * Instantiates a new elevation model. 58 * 59 * @param name the name of the model 60 * @param data the GPX data 61 */ 62 public ElevationModel(String name, GpxData data) { 63 gpxData = data; 64 this.name = name; 65 GpxIterator.visit(data, this); 66 } 67 68 /** 69 * Gets the GPX data instance used by this model. 70 * 71 * @return 72 */ 73 public GpxData getGpxData() { 74 return gpxData; 75 } 76 77 /** 78 * @return the tracks 79 */ 80 protected WayPointMap getTracks() { 81 return profiles; 82 } 83 84 /** 85 * Fires the 'model changed' event to all listeners. 86 */ 87 protected void fireModelChanged() { 88 for (IElevationModelListener listener : listeners) { 89 if (profiles != null && profiles.size() > 0) 90 listener.elevationProfileChanged(getCurrentProfile()); 91 } 92 } 93 94 /* (non-Javadoc) 95 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#addModelListener(org.openstreetmap.josm.plugins.elevation.IElevationModelListener) 96 */ 97 @Override 98 public void addModelListener(IElevationModelListener listener) { 99 this.listeners.add(listener); 100 } 101 102 /* (non-Javadoc) 103 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#removeModelListener(org.openstreetmap.josm.plugins.elevation.IElevationModelListener) 104 */ 105 @Override 106 public void removeModelListener(IElevationModelListener listener) { 107 this.listeners.remove(listener); 108 } 109 110 /* (non-Javadoc) 111 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#removeAllListeners() 112 */ 113 @Override 114 public void removeAllListeners() { 115 this.listeners.clear(); 116 } 117 118 /* (non-Javadoc) 119 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#getProfiles() 120 */ 121 @Override 122 public List<IElevationProfile> getProfiles() { 123 return profiles; 124 } 125 126 /* (non-Javadoc) 127 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#getCurrentProfile() 128 */ 129 @Override 130 public IElevationProfile getCurrentProfile() { 131 if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null; 132 133 return profiles.get(currentProfileIndex); 134 } 135 136 /* (non-Javadoc) 137 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#setCurrentProfile(org.openstreetmap.josm.plugins.elevation.IElevationProfile) 138 */ 139 @Override 140 public void setCurrentProfile(IElevationProfile newProfile) { 141 CheckParameterUtil.ensureParameterNotNull(newProfile); 142 143 if (!profiles.contains(newProfile)) { 144 profiles.add(newProfile); 145 } 146 147 setCurrentProfile(profiles.indexOf(newProfile)); 148 } 149 150 /* (non-Javadoc) 151 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#setCurrentProfile(int) 152 */ 153 @Override 154 public void setCurrentProfile(int index) { 155 if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount()); 156 157 currentProfileIndex = index; 158 fireModelChanged(); 159 } 160 161 /* (non-Javadoc) 162 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#profileCount() 163 */ 164 @Override 165 public int profileCount() { 166 return profiles != null ? profiles.size() : 0; 167 } 168 169 // Visitor stuff starts here... 170 171 /* (non-Javadoc) 172 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginWayPoints() 173 */ 174 public void beginWayPoints() { 175 // we ignore single way points (elevation profile is quite meaningless...) 176 } 177 178 /* (non-Javadoc) 179 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endWayPoints() 180 */ 181 public void endWayPoints() { 182 // we ignore single way points (elevation profile is quite meaningless...) 183 } 184 185 /* (non-Javadoc) 186 * @see org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#visit(org.openstreetmap.josm.data.gpx.WayPoint) 187 */ 188 @Override 189 public void visitWayPoint(WayPoint wp) { 190 // we ignore single way points (elevation profile is quite meaningless...) 191 } 192 193 194 /* (non-Javadoc) 195 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginTrack(org.openstreetmap.josm.data.gpx.GpxTrack) 196 */ 197 @Override 198 public void beginTrack(GpxTrack track) { 199 createProfile(track); 200 } 201 202 /* (non-Javadoc) 203 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endTrack(org.openstreetmap.josm.data.gpx.GpxTrack) 204 */ 205 @Override 206 public void endTrack(GpxTrack track) { 207 if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile"); 208 209 curProfile.setDistance(track.length()); 210 commitProfile(); 211 } 212 213 /* (non-Javadoc) 214 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginTrackSegment(org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment) 215 */ 216 @Override 217 public void beginTrackSegment(GpxTrack track, GpxTrackSegment segment) { 218 // Nothing to do here for now 219 } 220 221 /* (non-Javadoc) 222 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endTrackSegment(org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment) 223 */ 224 @Override 225 public void endTrackSegment(GpxTrack track, GpxTrackSegment segment) { 226 // Nothing to do here for now 227 } 228 229 /* (non-Javadoc) 230 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#visitTrackPoint(org.openstreetmap.josm.data.gpx.WayPoint, org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment) 231 */ 232 @Override 233 public void visitTrackPoint(WayPoint wp, GpxTrack track, 234 GpxTrackSegment segment) { 235 236 processWayPoint(wp); 237 } 238 239 240 /* (non-Javadoc) 241 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginRoute(org.openstreetmap.josm.data.gpx.GpxRoute) 242 */ 243 @Override 244 public void beginRoute(GpxRoute route) { 245 createProfile(route); 246 } 247 248 /* (non-Javadoc) 249 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endRoute(org.openstreetmap.josm.data.gpx.GpxRoute) 250 */ 251 @Override 252 public void endRoute(GpxRoute route) { 253 if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile"); 254 // a GpxRoute has no 'length' property 255 curProfile.setDistance(0); 256 commitProfile(); 257 } 258 259 /* (non-Javadoc) 260 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#visitRoutePoint(org.openstreetmap.josm.data.gpx.WayPoint, org.openstreetmap.josm.data.gpx.GpxRoute) 261 */ 262 @Override 263 public void visitRoutePoint(WayPoint wp, GpxRoute route) { 264 processWayPoint(wp); 265 } 266 267 /** 268 * Creates a new profile. 269 * 270 * @param trackOrRoute the track or route 271 */ 272 private void createProfile(IWithAttributes trackOrRoute) { 273 // check GPX data 274 String trackName = (String) trackOrRoute.get("name"); 275 276 if (trackName == null) { 277 trackName = (String) trackOrRoute.get(GpxData.META_NAME); 278 if (trackName == null) { 279 // no name given, build artificial one 280 trackName = name + "." + trackCounter; 281 } 282 } 283 284 curProfile = new ElevationProfile(trackName); 285 } 286 287 /** 288 * Adds a track or route to the internal track list. 289 * 290 * @param trackName the track name 291 */ 292 private void commitProfile() { 293 if (buffer.size() > 0) { 294 // assign way points to profile... 295 curProfile.setWayPoints(buffer); 296 // ... and add to profile list 297 profiles.add(curProfile); 298 buffer.clear(); 299 } 300 } 301 302 /** 303 * Adds the given way point to the current buffer. 304 * 305 * @param wp the wp 306 */ 307 private void processWayPoint(WayPoint wp) { 308 if (wp == null) { 309 throw new RuntimeException("WPT must not be null!"); 310 } 311 312 buffer.add(wp); 313 } 26 // private int sliceSize; 27 private int trackCounter; 28 private final GpxData gpxData; 29 private final String name; 30 private final WayPointMap profiles = new WayPointMap(); 31 private final List<IElevationModelListener> listeners = new ArrayList<IElevationModelListener>(); 32 private final List<WayPoint> buffer = new ArrayList<WayPoint>(); 33 private int currentProfileIndex = 0; 34 private ElevationProfile curProfile = null; 35 36 /** 37 * Instantiates a new elevation model. 38 */ 39 public ElevationModel() { 40 this("", null); 41 } 42 43 /** 44 * Instantiates a new elevation model. 45 * 46 * @param name the name of the model 47 * @param data the GPX data 48 */ 49 public ElevationModel(String name, GpxData data) { 50 gpxData = data; 51 this.name = name; 52 GpxIterator.visit(data, this); 53 } 54 55 /** 56 * Gets the GPX data instance used by this model. 57 * 58 * @return 59 */ 60 public GpxData getGpxData() { 61 return gpxData; 62 } 63 64 /** 65 * @return the tracks 66 */ 67 protected WayPointMap getTracks() { 68 return profiles; 69 } 70 71 /** 72 * Fires the 'model changed' event to all listeners. 73 */ 74 protected void fireModelChanged() { 75 for (IElevationModelListener listener : listeners) { 76 if (profiles != null && profiles.size() > 0) 77 listener.elevationProfileChanged(getCurrentProfile()); 78 } 79 } 80 81 @Override 82 public void addModelListener(IElevationModelListener listener) { 83 this.listeners.add(listener); 84 } 85 86 @Override 87 public void removeModelListener(IElevationModelListener listener) { 88 this.listeners.remove(listener); 89 } 90 91 @Override 92 public void removeAllListeners() { 93 this.listeners.clear(); 94 } 95 96 @Override 97 public List<IElevationProfile> getProfiles() { 98 return profiles; 99 } 100 101 @Override 102 public IElevationProfile getCurrentProfile() { 103 if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null; 104 105 return profiles.get(currentProfileIndex); 106 } 107 108 @Override 109 public void setCurrentProfile(IElevationProfile newProfile) { 110 CheckParameterUtil.ensureParameterNotNull(newProfile); 111 112 if (!profiles.contains(newProfile)) { 113 profiles.add(newProfile); 114 } 115 116 setCurrentProfile(profiles.indexOf(newProfile)); 117 } 118 119 @Override 120 public void setCurrentProfile(int index) { 121 if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount()); 122 123 currentProfileIndex = index; 124 fireModelChanged(); 125 } 126 127 @Override 128 public int profileCount() { 129 return profiles != null ? profiles.size() : 0; 130 } 131 132 // Visitor stuff starts here... 133 134 @Override 135 public void beginWayPoints() { 136 // we ignore single way points (elevation profile is quite meaningless...) 137 } 138 139 @Override 140 public void endWayPoints() { 141 // we ignore single way points (elevation profile is quite meaningless...) 142 } 143 144 @Override 145 public void visitWayPoint(WayPoint wp) { 146 // we ignore single way points (elevation profile is quite meaningless...) 147 } 148 149 150 @Override 151 public void beginTrack(GpxTrack track) { 152 createProfile(track); 153 } 154 155 @Override 156 public void endTrack(GpxTrack track) { 157 if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile"); 158 159 curProfile.setDistance(track.length()); 160 commitProfile(); 161 } 162 163 @Override 164 public void beginTrackSegment(GpxTrack track, GpxTrackSegment segment) { 165 // Nothing to do here for now 166 } 167 168 @Override 169 public void endTrackSegment(GpxTrack track, GpxTrackSegment segment) { 170 // Nothing to do here for now 171 } 172 173 @Override 174 public void visitTrackPoint(WayPoint wp, GpxTrack track, 175 GpxTrackSegment segment) { 176 177 processWayPoint(wp); 178 } 179 180 @Override 181 public void beginRoute(GpxRoute route) { 182 createProfile(route); 183 } 184 185 @Override 186 public void endRoute(GpxRoute route) { 187 if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile"); 188 // a GpxRoute has no 'length' property 189 curProfile.setDistance(0); 190 commitProfile(); 191 } 192 193 @Override 194 public void visitRoutePoint(WayPoint wp, GpxRoute route) { 195 processWayPoint(wp); 196 } 197 198 /** 199 * Creates a new profile. 200 * 201 * @param trackOrRoute the track or route 202 */ 203 private void createProfile(IWithAttributes trackOrRoute) { 204 // check GPX data 205 String trackName = (String) trackOrRoute.get("name"); 206 207 if (trackName == null) { 208 trackName = (String) trackOrRoute.get(GpxData.META_NAME); 209 if (trackName == null) { 210 // no name given, build artificial one 211 trackName = name + "." + trackCounter; 212 } 213 } 214 215 curProfile = new ElevationProfile(trackName); 216 } 217 218 /** 219 * Adds a track or route to the internal track list. 220 * 221 * @param trackName the track name 222 */ 223 private void commitProfile() { 224 if (buffer.size() > 0) { 225 // assign way points to profile... 226 curProfile.setWayPoints(buffer); 227 // ... and add to profile list 228 profiles.add(curProfile); 229 buffer.clear(); 230 } 231 } 232 233 /** 234 * Adds the given way point to the current buffer. 235 * 236 * @param wp the wp 237 */ 238 private void processWayPoint(WayPoint wp) { 239 if (wp == null) { 240 throw new RuntimeException("WPT must not be null!"); 241 } 242 243 buffer.add(wp); 244 } 314 245 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java
r29962 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 23 10 import org.openstreetmap.josm.plugins.elevation.ElevationHelper; 24 11 import org.openstreetmap.josm.plugins.elevation.IElevationProfile; 12 25 13 26 14 /** … … 45 33 */ 46 34 public class ElevationProfile implements IElevationProfile, 47 IGpxWaypointVisitor { 48 public static final int WAYPOINT_START = 0; 49 public static final int WAYPOINT_END = 1; 50 public static final int WAYPOINT_MIN = 2; 51 public static final int WAYPOINT_MAX = 3; 52 53 private String name; 54 private int minHeight; 55 private int maxHeight; 56 private int avrgHeight; 57 private double dist; 58 private Date start = new Date(); 59 private Date end = new Date(); 60 private WayPoint[] importantWayPoints = new WayPoint[4]; 61 private IElevationProfile parent; 62 private int sumEle; // temp var for average height 63 private List<WayPoint> wayPoints; 64 private int numWayPoints; // cached value 65 private int gain; 66 private int lastEle; 67 private Bounds bounds; 68 69 private static boolean ignoreZeroHeight = true; 70 71 /** 72 * Creates a name elevation profile without any way points. 73 * 74 * @param name 75 */ 76 public ElevationProfile(String name) { 77 this(name, null, null, 0); 78 } 79 80 /** 81 * Creates a name elevation profile with a given set of way points. 82 * 83 * @param name 84 * The name of the profile. 85 * @param parent 86 * The (optional) parent profile. 87 * @param wayPoints 88 * The list containing the way points of the profile. 89 * @param sliceSize 90 * The requested target size of the profile. 91 */ 92 public ElevationProfile(String name, IElevationProfile parent, 93 List<WayPoint> wayPoints, int sliceSize) { 94 super(); 95 this.name = name; 96 this.parent = parent; 97 98 setWayPoints(wayPoints); 99 } 100 101 /** 102 * Checks if zero elevation should be ignored or not. 103 * 104 * @return true, if is ignore zero height 105 */ 106 public static boolean isIgnoreZeroHeight() { 107 return ignoreZeroHeight; 108 } 109 110 /** 111 * Sets the ignore zero height. 112 * 113 * @param ignoreZeroHeight the new ignore zero height 114 */ 115 public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) { 116 ElevationProfile.ignoreZeroHeight = ignoreZeroHeight; 117 } 118 119 /* 120 * (non-Javadoc) 121 * 122 * @see 123 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#invalidateModel 124 * (int) 125 */ 126 public void updateElevationData() { 127 updateValues(); 128 } 129 130 /** 131 * Revisits all way points and recomputes the characteristic values like 132 * min/max elevation. 133 */ 134 protected void updateValues() { 135 if (wayPoints == null) 136 return; 137 138 int n = this.wayPoints.size(); 139 if (n == 0) 140 return; 141 142 start = new Date(); 143 end = new Date(0L); 144 this.minHeight = Integer.MAX_VALUE; 145 this.maxHeight = Integer.MIN_VALUE; 146 sumEle = 0; 147 gain = 0; 148 lastEle = 0; 149 150 for (WayPoint wayPoint : this.wayPoints) { 151 visitWayPoint(wayPoint); 152 } 153 154 if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) { 155 // file does not contain elevation data at all 156 minHeight = 0; 157 maxHeight = 0; 158 setMinWayPoint(wayPoints.get(0)); 159 setMaxWayPoint(wayPoints.get(n-1)); 160 } 161 162 //if (start.after(end) || start.equals(end)) { 163 // GPX does not contain time stamps -> use sequential order 164 setStart(wayPoints.get(0)); 165 setEnd(wayPoints.get(n-1)); 166 //} 167 168 avrgHeight = sumEle / n; 169 } 170 171 /** 172 * Gets the name of the profile. 173 */ 174 public String getName() { 175 return name; 176 } 177 178 /** 179 * Sets the name of the profile. 180 * @param name The new name of the profile. 181 */ 182 public void setName(String name) { 183 this.name = name; 184 } 185 186 /** 187 * Sets the way point with the lowest elevation. 188 * @param wp The way point instance having the lowest elevation. 189 */ 190 protected void setMinWayPoint(WayPoint wp) { 191 importantWayPoints[WAYPOINT_MIN] = wp; 192 this.minHeight = (int) ElevationHelper.getElevation(wp); 193 } 194 195 /** 196 * Sets the way point with the highest elevation. 197 * @param wp The way point instance having the highest elevation. 198 */ 199 protected void setMaxWayPoint(WayPoint wp) { 200 importantWayPoints[WAYPOINT_MAX] = wp; 201 this.maxHeight = (int) ElevationHelper.getElevation(wp); 202 } 203 204 /** 205 * Sets the average height. 206 * @param avrgHeight 207 */ 208 protected void setAvrgHeight(int avrgHeight) { 209 this.avrgHeight = avrgHeight; 210 } 211 212 /** 213 * Sets the very first way point. 214 * @param wp 215 */ 216 protected void setStart(WayPoint wp) { 217 importantWayPoints[WAYPOINT_START] = wp; 218 this.start = wp.getTime(); 219 } 220 221 /** 222 * Sets the very last way point. 223 * @param wp 224 */ 225 protected void setEnd(WayPoint wp) { 226 importantWayPoints[WAYPOINT_END] = wp; 227 this.end = wp.getTime(); 228 } 229 230 public void setParent(IElevationProfile parent) { 231 this.parent = parent; 232 } 233 234 /** 235 * Sets the way points of this profile. 236 * 237 * @param wayPoints 238 */ 239 public void setWayPoints(List<WayPoint> wayPoints) { 240 if (this.wayPoints != wayPoints) { 241 this.wayPoints = new ArrayList<WayPoint>(wayPoints); 242 numWayPoints = wayPoints != null ? wayPoints.size() : 0; 243 updateValues(); 244 245 } 246 } 247 248 /** 249 * Checks if the given index is valid or not. 250 * 251 * @param index 252 * The index to check. 253 * @return true, if the given index is valid; otherwise false. 254 */ 255 protected boolean checkIndex(int index) { 256 return index >= 0 && index < getNumberOfWayPoints(); 257 } 258 259 /* 260 * (non-Javadoc) 261 * 262 * @see 263 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#elevationValueAt 264 * (int) 265 */ 266 public int elevationValueAt(int i) { 267 if (checkIndex(i)) { 268 return (int) ElevationHelper.getElevation(wayPoints.get(i)); 269 } else { 270 throw new IndexOutOfBoundsException(String.format( 271 "Invalid index: %d, expected 0..%d", i, 272 getNumberOfWayPoints())); 273 } 274 } 275 276 /* 277 * (non-Javadoc) 278 * 279 * @see 280 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getAverageHeight 281 * () 282 */ 283 public int getAverageHeight() { 284 return avrgHeight; 285 } 286 287 /* 288 * (non-Javadoc) 289 * 290 * @see 291 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getChildren() 292 */ 293 public List<IElevationProfile> getChildren() { 294 return null; 295 } 296 297 /* 298 * (non-Javadoc) 299 * 300 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEnd() 301 */ 302 public Date getEnd() { 303 return end; 304 } 305 306 /* 307 * (non-Javadoc) 308 * 309 * @see 310 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxHeight() 311 */ 312 public int getMaxHeight() { 313 return maxHeight; 314 } 315 316 /* 317 * (non-Javadoc) 318 * 319 * @see 320 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinHeight() 321 */ 322 public int getMinHeight() { 323 return minHeight; 324 } 325 326 /** 327 * Gets the difference between min and max elevation. 328 * 329 * @return 330 */ 331 public int getHeightDifference() { 332 return maxHeight - minHeight; 333 } 334 335 /** 336 * Gets the elevation gain. 337 * 338 * @return 339 */ 340 public int getGain() { 341 return gain; 342 } 343 344 345 /* (non-Javadoc) 346 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getDistance() 347 */ 348 @Override 349 public double getDistance() { 350 return dist; // dist is in meters 351 } 352 353 /** 354 * Sets the distance of the elevation profile. 355 * @param dist 356 */ 357 protected void setDistance(double dist) { 358 this.dist = dist; 359 } 360 361 /** 362 * Returns the time between start and end of the track. 363 * @return 364 */ 365 public long getTimeDifference() { 366 WayPoint wp1 = getStartWayPoint(); 367 WayPoint wp2 = getEndWayPoint(); 368 369 if (wp1 != null && wp2 != null) { 370 long diff = wp2.getTime().getTime() - wp1.getTime().getTime(); 371 return diff; 372 } 373 374 return 0L; 375 } 376 377 /* 378 * (non-Javadoc) 379 * 380 * @see 381 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getParent() 382 */ 383 public IElevationProfile getParent() { 384 return parent; 385 } 386 387 /* 388 * (non-Javadoc) 389 * 390 * @see 391 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStart() 392 */ 393 394 public Date getStart() { 395 return start; 396 } 397 398 /* 399 * (non-Javadoc) 400 * 401 * @see 402 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEndWayPoint 403 * () 404 */ 405 406 public WayPoint getEndWayPoint() { 407 return importantWayPoints[WAYPOINT_END]; 408 } 409 410 /* 411 * (non-Javadoc) 412 * 413 * @see 414 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxWayPoint 415 * () 416 */ 417 418 public WayPoint getMaxWayPoint() { 419 return importantWayPoints[WAYPOINT_MAX]; 420 } 421 422 /* 423 * (non-Javadoc) 424 * 425 * @see 426 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinWayPoint 427 * () 428 */ 429 430 public WayPoint getMinWayPoint() { 431 return importantWayPoints[WAYPOINT_MIN]; 432 } 433 434 /* 435 * (non-Javadoc) 436 * 437 * @see 438 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStartWayPoint 439 * () 440 */ 441 public WayPoint getStartWayPoint() { 442 return importantWayPoints[WAYPOINT_START]; 443 } 444 445 /* 446 * (non-Javadoc) 447 * 448 * @see 449 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getWayPoints() 450 */ 451 public List<WayPoint> getWayPoints() { 452 return wayPoints; 453 } 454 455 /* 456 * (non-Javadoc) 457 * 458 * @seeorg.openstreetmap.josm.plugins.elevation.ElevationProfileBase# 459 * getNumberOfWayPoints() 460 */ 461 public int getNumberOfWayPoints() { 462 return numWayPoints;// wayPoints != null ? wayPoints.size() : 0; 463 } 464 465 /** 466 * Gets the coordinate bounds of this profile. See {@link Bounds} for details. 467 * 468 * @return the bounds of this elevation profile 469 */ 470 public Bounds getBounds() { 471 return bounds; 472 } 473 474 /** 475 * Gets a flag indicating whether the associated way points contained 476 * elevation data or not. This is the case if min and max height or both 477 * zero. 478 * 479 * @return 480 */ 481 public boolean hasElevationData() { 482 return minHeight != maxHeight; 483 } 484 485 /** 486 * Visits a way point in order to update statistical values about the given 487 * way point list. 488 */ 489 public void visitWayPoint(WayPoint wp) { 490 if (wp.getTime().after(end)) { 491 setEnd(wp); 492 } 493 494 if (wp.getTime().before(start)) { 495 setStart(wp); 496 } 497 498 // update boundaries 499 if (bounds == null) { 500 bounds = new Bounds(wp.getCoor()); 501 } else { 502 bounds.extend(wp.getCoor()); 503 } 504 505 int ele = (int) ElevationHelper.getElevation(wp); 506 507 if (!isIgnoreZeroHeight() || ele > 0) { 508 if (ele > maxHeight) { 509 setMaxWayPoint(wp); 510 } 511 if (ele < minHeight) { 512 setMinWayPoint(wp); 513 } 514 515 if (ele > lastEle) { 516 gain += ele - lastEle; 517 } 518 519 sumEle += ele; 520 lastEle = ele; 521 } 522 } 523 524 public String toString() { 525 return name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd() 526 + ", minHeight=" + getMinHeight() + ", maxHeight=" 527 + getMaxHeight() + "]";*/ 528 } 35 IGpxWaypointVisitor { 36 public static final int WAYPOINT_START = 0; 37 public static final int WAYPOINT_END = 1; 38 public static final int WAYPOINT_MIN = 2; 39 public static final int WAYPOINT_MAX = 3; 40 41 private String name; 42 private int minHeight; 43 private int maxHeight; 44 private int avrgHeight; 45 private double dist; 46 private Date start = new Date(); 47 private Date end = new Date(); 48 private final WayPoint[] importantWayPoints = new WayPoint[4]; 49 private IElevationProfile parent; 50 private int sumEle; // temp var for average height 51 private List<WayPoint> wayPoints; 52 private int numWayPoints; // cached value 53 private int gain; 54 private int lastEle; 55 private Bounds bounds; 56 57 private static boolean ignoreZeroHeight = true; 58 59 /** 60 * Creates a name elevation profile without any way points. 61 * 62 * @param name 63 */ 64 public ElevationProfile(String name) { 65 this(name, null, null, 0); 66 } 67 68 /** 69 * Creates a name elevation profile with a given set of way points. 70 * 71 * @param name 72 * The name of the profile. 73 * @param parent 74 * The (optional) parent profile. 75 * @param wayPoints 76 * The list containing the way points of the profile. 77 * @param sliceSize 78 * The requested target size of the profile. 79 */ 80 public ElevationProfile(String name, IElevationProfile parent, 81 List<WayPoint> wayPoints, int sliceSize) { 82 super(); 83 this.name = name; 84 this.parent = parent; 85 86 setWayPoints(wayPoints); 87 } 88 89 /** 90 * Checks if zero elevation should be ignored or not. 91 * 92 * @return true, if is ignore zero height 93 */ 94 public static boolean isIgnoreZeroHeight() { 95 return ignoreZeroHeight; 96 } 97 98 /** 99 * Sets the ignore zero height. 100 * 101 * @param ignoreZeroHeight the new ignore zero height 102 */ 103 public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) { 104 ElevationProfile.ignoreZeroHeight = ignoreZeroHeight; 105 } 106 107 @Override 108 public void updateElevationData() { 109 updateValues(); 110 } 111 112 /** 113 * Revisits all way points and recomputes the characteristic values like 114 * min/max elevation. 115 */ 116 protected void updateValues() { 117 if (wayPoints == null) 118 return; 119 120 int n = this.wayPoints.size(); 121 if (n == 0) 122 return; 123 124 start = new Date(); 125 end = new Date(0L); 126 this.minHeight = Integer.MAX_VALUE; 127 this.maxHeight = Integer.MIN_VALUE; 128 sumEle = 0; 129 gain = 0; 130 lastEle = 0; 131 132 for (WayPoint wayPoint : this.wayPoints) { 133 visitWayPoint(wayPoint); 134 } 135 136 if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) { 137 // file does not contain elevation data at all 138 minHeight = 0; 139 maxHeight = 0; 140 setMinWayPoint(wayPoints.get(0)); 141 setMaxWayPoint(wayPoints.get(n-1)); 142 } 143 144 //if (start.after(end) || start.equals(end)) { 145 // GPX does not contain time stamps -> use sequential order 146 setStart(wayPoints.get(0)); 147 setEnd(wayPoints.get(n-1)); 148 //} 149 150 avrgHeight = sumEle / n; 151 } 152 153 /** 154 * Gets the name of the profile. 155 */ 156 @Override 157 public String getName() { 158 return name; 159 } 160 161 /** 162 * Sets the name of the profile. 163 * @param name The new name of the profile. 164 */ 165 public void setName(String name) { 166 this.name = name; 167 } 168 169 /** 170 * Sets the way point with the lowest elevation. 171 * @param wp The way point instance having the lowest elevation. 172 */ 173 protected void setMinWayPoint(WayPoint wp) { 174 importantWayPoints[WAYPOINT_MIN] = wp; 175 this.minHeight = (int) ElevationHelper.getElevation(wp); 176 } 177 178 /** 179 * Sets the way point with the highest elevation. 180 * @param wp The way point instance having the highest elevation. 181 */ 182 protected void setMaxWayPoint(WayPoint wp) { 183 importantWayPoints[WAYPOINT_MAX] = wp; 184 this.maxHeight = (int) ElevationHelper.getElevation(wp); 185 } 186 187 /** 188 * Sets the average height. 189 * @param avrgHeight 190 */ 191 protected void setAvrgHeight(int avrgHeight) { 192 this.avrgHeight = avrgHeight; 193 } 194 195 /** 196 * Sets the very first way point. 197 * @param wp 198 */ 199 protected void setStart(WayPoint wp) { 200 importantWayPoints[WAYPOINT_START] = wp; 201 this.start = wp.getTime(); 202 } 203 204 /** 205 * Sets the very last way point. 206 * @param wp 207 */ 208 protected void setEnd(WayPoint wp) { 209 importantWayPoints[WAYPOINT_END] = wp; 210 this.end = wp.getTime(); 211 } 212 213 public void setParent(IElevationProfile parent) { 214 this.parent = parent; 215 } 216 217 /** 218 * Sets the way points of this profile. 219 * 220 * @param wayPoints 221 */ 222 public void setWayPoints(List<WayPoint> wayPoints) { 223 if (this.wayPoints != wayPoints) { 224 this.wayPoints = new ArrayList<WayPoint>(wayPoints); 225 numWayPoints = wayPoints != null ? wayPoints.size() : 0; 226 updateValues(); 227 228 } 229 } 230 231 /** 232 * Checks if the given index is valid or not. 233 * 234 * @param index 235 * The index to check. 236 * @return true, if the given index is valid; otherwise false. 237 */ 238 protected boolean checkIndex(int index) { 239 return index >= 0 && index < getNumberOfWayPoints(); 240 } 241 242 @Override 243 public int elevationValueAt(int i) { 244 if (checkIndex(i)) { 245 return (int) ElevationHelper.getElevation(wayPoints.get(i)); 246 } else { 247 throw new IndexOutOfBoundsException(String.format( 248 "Invalid index: %d, expected 0..%d", i, 249 getNumberOfWayPoints())); 250 } 251 } 252 253 @Override 254 public int getAverageHeight() { 255 return avrgHeight; 256 } 257 258 @Override 259 public List<IElevationProfile> getChildren() { 260 return null; 261 } 262 263 @Override 264 public Date getEnd() { 265 return end; 266 } 267 268 @Override 269 public int getMaxHeight() { 270 return maxHeight; 271 } 272 273 @Override 274 public int getMinHeight() { 275 return minHeight; 276 } 277 278 /** 279 * Gets the difference between min and max elevation. 280 * 281 * @return 282 */ 283 @Override 284 public int getHeightDifference() { 285 return maxHeight - minHeight; 286 } 287 288 /** 289 * Gets the elevation gain. 290 * 291 * @return 292 */ 293 @Override 294 public int getGain() { 295 return gain; 296 } 297 298 @Override 299 public double getDistance() { 300 return dist; // dist is in meters 301 } 302 303 /** 304 * Sets the distance of the elevation profile. 305 * @param dist 306 */ 307 protected void setDistance(double dist) { 308 this.dist = dist; 309 } 310 311 /** 312 * Returns the time between start and end of the track. 313 * @return 314 */ 315 @Override 316 public long getTimeDifference() { 317 WayPoint wp1 = getStartWayPoint(); 318 WayPoint wp2 = getEndWayPoint(); 319 320 if (wp1 != null && wp2 != null) { 321 long diff = wp2.getTime().getTime() - wp1.getTime().getTime(); 322 return diff; 323 } 324 325 return 0L; 326 } 327 328 @Override 329 public IElevationProfile getParent() { 330 return parent; 331 } 332 333 @Override 334 public Date getStart() { 335 return start; 336 } 337 338 @Override 339 public WayPoint getEndWayPoint() { 340 return importantWayPoints[WAYPOINT_END]; 341 } 342 343 @Override 344 public WayPoint getMaxWayPoint() { 345 return importantWayPoints[WAYPOINT_MAX]; 346 } 347 348 @Override 349 public WayPoint getMinWayPoint() { 350 return importantWayPoints[WAYPOINT_MIN]; 351 } 352 353 @Override 354 public WayPoint getStartWayPoint() { 355 return importantWayPoints[WAYPOINT_START]; 356 } 357 358 @Override 359 public List<WayPoint> getWayPoints() { 360 return wayPoints; 361 } 362 363 @Override 364 public int getNumberOfWayPoints() { 365 return numWayPoints;// wayPoints != null ? wayPoints.size() : 0; 366 } 367 368 /** 369 * Gets the coordinate bounds of this profile. See {@link Bounds} for details. 370 * 371 * @return the bounds of this elevation profile 372 */ 373 @Override 374 public Bounds getBounds() { 375 return bounds; 376 } 377 378 /** 379 * Gets a flag indicating whether the associated way points contained 380 * elevation data or not. This is the case if min and max height or both 381 * zero. 382 * 383 * @return 384 */ 385 @Override 386 public boolean hasElevationData() { 387 return minHeight != maxHeight; 388 } 389 390 /** 391 * Visits a way point in order to update statistical values about the given 392 * way point list. 393 */ 394 @Override 395 public void visitWayPoint(WayPoint wp) { 396 if (wp.getTime().after(end)) { 397 setEnd(wp); 398 } 399 400 if (wp.getTime().before(start)) { 401 setStart(wp); 402 } 403 404 // update boundaries 405 if (bounds == null) { 406 bounds = new Bounds(wp.getCoor()); 407 } else { 408 bounds.extend(wp.getCoor()); 409 } 410 411 int ele = (int) ElevationHelper.getElevation(wp); 412 413 if (!isIgnoreZeroHeight() || ele > 0) { 414 if (ele > maxHeight) { 415 setMaxWayPoint(wp); 416 } 417 if (ele < minHeight) { 418 setMinWayPoint(wp); 419 } 420 421 if (ele > lastEle) { 422 gain += ele - lastEle; 423 } 424 425 sumEle += ele; 426 lastEle = ele; 427 } 428 } 429 430 @Override 431 public String toString() { 432 return name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd() 433 + ", minHeight=" + getMinHeight() + ", maxHeight=" 434 + getMaxHeight() + "]";*/ 435 } 529 436 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationWayPointKind.java
r29907 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 20 7 */ 21 8 public enum ElevationWayPointKind { 22 Plain,// Simple way point (equal to no or low slope)23 Highlighted,// Highlighted waypoint24 StartPoint,// First way point25 EndPoint,// Last way point26 MaxElevation,// Highest way point27 MinElevation, // Lowest way point 28 ElevationGainHigh,// Elevation gain (high slope 15-25%)29 ElevationLossHigh,// Elevation loss (high downward slope)30 ElevationGainLow,// Elevation gain (low slope, 5-14.9%)31 ElevationLossLow,// Elevation loss (low downward slope)32 ElevationLevelGain,// Elevation level gain (e. g. crossed 300m from lower elevation)33 ElevationLevelLoss,// Elevation level (e. g. crossed 300m from higher elevation)34 FullHour // Full Hour 9 Plain, // Simple way point (equal to no or low slope) 10 Highlighted, // Highlighted waypoint 11 StartPoint, // First way point 12 EndPoint, // Last way point 13 MaxElevation, // Highest way point 14 MinElevation, // Lowest way point 15 ElevationGainHigh, // Elevation gain (high slope 15-25%) 16 ElevationLossHigh, // Elevation loss (high downward slope) 17 ElevationGainLow, // Elevation gain (low slope, 5-14.9%) 18 ElevationLossLow, // Elevation loss (low downward slope) 19 ElevationLevelGain, // Elevation level gain (e. g. crossed 300m from lower elevation) 20 ElevationLevelLoss, // Elevation level (e. g. crossed 300m from higher elevation) 21 FullHour // Full Hour 35 22 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GeoidCorrectionKind.java
r29907 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 17 4 /** 18 5 * @author Oliver Wieland <oliver.wieland@online.de> 19 * Enumeration for available elevation correction modes. 6 * Enumeration for available elevation correction modes. 20 7 */ 21 8 public enum GeoidCorrectionKind { 22 23 24 25 26 27 9 /** Elevation values remain unchanged */ 10 None, 11 /** Automatic correction by geoid lookup table */ 12 Auto, 13 /** Fixed value */ 14 Fixed 28 15 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GpxIterator.java
r29962 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 28 15 */ 29 16 public class GpxIterator { 30 /** 31 * Static class, no need to instantiate me. 32 */ 33 private GpxIterator() {} 34 35 /** 36 * Runs the given visitor on a GPX data instance. If one or both 37 * arguments are null, this method will return immediately. 38 * 39 * @param data 40 * The GPX data instance. 41 * @param visitor 42 * The visitor which inspects all GPX entities. 43 */ 44 public static void visit(GpxData data, IGpxVisitor visitor) { 45 if (data == null) return; 46 if (visitor == null) return; 47 48 if (data.isEmpty()) return; 49 50 visitor.beginWayPoints(); 51 visitSingleWaypoints(data, visitor); 52 visitor.endWayPoints(); 17 /** 18 * Static class, no need to instantiate me. 19 */ 20 private GpxIterator() {} 53 21 54 // routes 55 if (data.hasRoutePoints()) { 56 for (GpxRoute rte : data.routes) { 57 visitRoute(visitor, rte); 58 } 59 } 22 /** 23 * Runs the given visitor on a GPX data instance. If one or both 24 * arguments are null, this method will return immediately. 25 * 26 * @param data 27 * The GPX data instance. 28 * @param visitor 29 * The visitor which inspects all GPX entities. 30 */ 31 public static void visit(GpxData data, IGpxVisitor visitor) { 32 if (data == null) return; 33 if (visitor == null) return; 60 34 61 // tracks 62 for (GpxTrack trk : data.tracks) { 63 visitTrack(visitor, trk); 64 } 65 } 66 67 /** 68 * Visits a single GPX track. 69 * @param track The track to visit. 70 * @param visitor 71 * The visitor which inspects all GPX entities. 72 */ 73 public static void visit(GpxTrack track, IGpxVisitor visitor) { 74 visitTrack(visitor, track); 75 } 76 77 /** 78 * Visits a single GPX route. 79 * @param route The route to visit. 80 * @param visitor 81 * The visitor which inspects all GPX entities. 82 */ 83 public static void visit(GpxRoute route, IGpxVisitor visitor) { 84 visitRoute(visitor, route); 85 } 35 if (data.isEmpty()) return; 86 36 87 // ---------------------- Helper methods ---------------- 88 89 /** 90 * @param visitor 91 * @param trk 92 */ 93 private static void visitTrack(IGpxVisitor visitor, GpxTrack trk) { 94 if (trk == null) return; 95 if (visitor == null) return; 96 97 Collection<GpxTrackSegment> segments = trk.getSegments(); 98 99 if (segments != null) { 100 visitor.beginTrack(trk); 101 // visit all segments 102 for (GpxTrackSegment segment : segments) { 103 Collection<WayPoint> waypts = segment.getWayPoints(); 104 // no visitor here... 105 if (waypts == null) 106 continue; 107 108 visitor.beginTrackSegment(trk, segment); 109 110 for (WayPoint wayPoint : waypts) { 111 visitor.visitTrackPoint(wayPoint, trk, segment); 112 } 113 114 visitor.endTrackSegment(trk, segment); 115 } 116 visitor.endTrack(trk); 117 } 118 119 } 37 visitor.beginWayPoints(); 38 visitSingleWaypoints(data, visitor); 39 visitor.endWayPoints(); 120 40 121 /** 122 * @param visitor 123 * @param route 124 */ 125 private static void visitRoute(IGpxVisitor visitor, GpxRoute route) { 126 if (route == null) return; 127 if (visitor == null) return; 128 129 visitor.beginWayPoints(); 130 for (WayPoint wpt : route.routePoints) { 131 visitor.visitRoutePoint(wpt, route); 132 } 133 visitor.endWayPoints(); 134 } 41 // routes 42 if (data.hasRoutePoints()) { 43 for (GpxRoute rte : data.routes) { 44 visitRoute(visitor, rte); 45 } 46 } 135 47 136 /** 137 * @param data 138 * @param visitor 139 */ 140 private static void visitSingleWaypoints(GpxData data, IGpxVisitor visitor) { 141 // isolated way points 142 if (data.waypoints != null) { // better with an hasWaypoints method!? 143 for (WayPoint wpt : data.waypoints) { 144 visitor.visitWayPoint(wpt); 145 } 146 } 147 } 48 // tracks 49 for (GpxTrack trk : data.tracks) { 50 visitTrack(visitor, trk); 51 } 52 } 53 54 /** 55 * Visits a single GPX track. 56 * @param track The track to visit. 57 * @param visitor 58 * The visitor which inspects all GPX entities. 59 */ 60 public static void visit(GpxTrack track, IGpxVisitor visitor) { 61 visitTrack(visitor, track); 62 } 63 64 /** 65 * Visits a single GPX route. 66 * @param route The route to visit. 67 * @param visitor 68 * The visitor which inspects all GPX entities. 69 */ 70 public static void visit(GpxRoute route, IGpxVisitor visitor) { 71 visitRoute(visitor, route); 72 } 73 74 // ---------------------- Helper methods ---------------- 75 76 /** 77 * @param visitor 78 * @param trk 79 */ 80 private static void visitTrack(IGpxVisitor visitor, GpxTrack trk) { 81 if (trk == null) return; 82 if (visitor == null) return; 83 84 Collection<GpxTrackSegment> segments = trk.getSegments(); 85 86 if (segments != null) { 87 visitor.beginTrack(trk); 88 // visit all segments 89 for (GpxTrackSegment segment : segments) { 90 Collection<WayPoint> waypts = segment.getWayPoints(); 91 // no visitor here... 92 if (waypts == null) 93 continue; 94 95 visitor.beginTrackSegment(trk, segment); 96 97 for (WayPoint wayPoint : waypts) { 98 visitor.visitTrackPoint(wayPoint, trk, segment); 99 } 100 101 visitor.endTrackSegment(trk, segment); 102 } 103 visitor.endTrack(trk); 104 } 105 106 } 107 108 /** 109 * @param visitor 110 * @param route 111 */ 112 private static void visitRoute(IGpxVisitor visitor, GpxRoute route) { 113 if (route == null) return; 114 if (visitor == null) return; 115 116 visitor.beginWayPoints(); 117 for (WayPoint wpt : route.routePoints) { 118 visitor.visitRoutePoint(wpt, route); 119 } 120 visitor.endWayPoints(); 121 } 122 123 /** 124 * @param data 125 * @param visitor 126 */ 127 private static void visitSingleWaypoints(GpxData data, IGpxVisitor visitor) { 128 // isolated way points 129 if (data.waypoints != null) { // better with an hasWaypoints method!? 130 for (WayPoint wpt : data.waypoints) { 131 visitor.visitWayPoint(wpt); 132 } 133 } 134 } 148 135 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxVisitor.java
r29962 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 25 12 */ 26 13 public interface IGpxVisitor extends IGpxWaypointVisitor { 27 /** 28 * Starts a GPX way point collection. 29 */ 30 void beginWayPoints(); 31 32 /** 33 * Ends a GPX way point collection. 34 */ 35 void endWayPoints(); 36 37 /** 38 * Starts a GPX track. 39 */ 40 void beginTrack(GpxTrack track); 41 42 /** 43 * Ends a GPX track. 44 */ 45 void endTrack(GpxTrack track); 46 47 /** 48 * Starts a GPX route. 49 */ 50 void beginRoute(GpxRoute track); 51 52 /** 53 * Ends a GPX route. 54 */ 55 void endRoute(GpxRoute track); 14 /** 15 * Starts a GPX way point collection. 16 */ 17 void beginWayPoints(); 56 18 57 58 /** 59 * Starts a segment within a GPX track. 60 */ 61 void beginTrackSegment(GpxTrack track, GpxTrackSegment segment); 62 63 /** 64 * Ends a segment within a GPX track. 65 */ 66 void endTrackSegment(GpxTrack track, GpxTrackSegment segment); 67 68 /** 69 * Visits a way point within a GPX route. 70 * @param route The route containing the way point. 71 * @param wp The way point to visit. 72 */ 73 void visitWayPoint(WayPoint wp); 74 75 /** 76 * Visits a way point within a GPX track. 77 * 78 * @param wp The way point to visit. 79 * @param track the track containing the way point. 80 * @param segment the track segment 81 */ 82 void visitTrackPoint(WayPoint wp, GpxTrack track, GpxTrackSegment segment); 83 84 /** 85 * Visits a way point within a GPX route. 86 * @param route the route containing the way point. 87 * @param wp the way point to visit. 88 */ 89 void visitRoutePoint(WayPoint wp, GpxRoute route); 19 /** 20 * Ends a GPX way point collection. 21 */ 22 void endWayPoints(); 23 24 /** 25 * Starts a GPX track. 26 */ 27 void beginTrack(GpxTrack track); 28 29 /** 30 * Ends a GPX track. 31 */ 32 void endTrack(GpxTrack track); 33 34 /** 35 * Starts a GPX route. 36 */ 37 void beginRoute(GpxRoute track); 38 39 /** 40 * Ends a GPX route. 41 */ 42 void endRoute(GpxRoute track); 43 44 45 /** 46 * Starts a segment within a GPX track. 47 */ 48 void beginTrackSegment(GpxTrack track, GpxTrackSegment segment); 49 50 /** 51 * Ends a segment within a GPX track. 52 */ 53 void endTrackSegment(GpxTrack track, GpxTrackSegment segment); 54 55 /** 56 * Visits a way point within a GPX route. 57 * @param route The route containing the way point. 58 * @param wp The way point to visit. 59 */ 60 @Override 61 void visitWayPoint(WayPoint wp); 62 63 /** 64 * Visits a way point within a GPX track. 65 * 66 * @param wp The way point to visit. 67 * @param track the track containing the way point. 68 * @param segment the track segment 69 */ 70 void visitTrackPoint(WayPoint wp, GpxTrack track, GpxTrackSegment segment); 71 72 /** 73 * Visits a way point within a GPX route. 74 * @param route the route containing the way point. 75 * @param wp the way point to visit. 76 */ 77 void visitRoutePoint(WayPoint wp, GpxRoute route); 90 78 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxWaypointVisitor.java
r29962 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gpx; 16 3 … … 22 9 */ 23 10 public interface IGpxWaypointVisitor { 24 25 26 * without an associated route or track. 27 28 29 11 /** 12 * Visits a way point. This method is called for isolated way points, i. e. way points 13 * without an associated route or track. 14 * @param wp The way point to visit. 15 */ 16 void visitWayPoint(WayPoint wp); 30 17 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/WayPointMap.java
r29955 r30344 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.plugins.elevation.gpx; 2 3 -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/EleCoordinate.java
r29964 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation.grid; 15 3 16 4 import org.openstreetmap.josm.data.coor.LatLon; 17 5 18 public class EleCoordinate extends LatLon { 6 public class EleCoordinate extends LatLon { 19 7 /** 20 8 * 21 9 */ 22 10 private static final long serialVersionUID = 9121465585197496570L; 23 24 private double ele = Double.NaN; 11 12 private double ele = Double.NaN; 25 13 26 14 public EleCoordinate() { 27 15 this(Double.NaN, Double.NaN, Double.NaN); 28 16 } 29 17 30 18 public EleCoordinate(double lat, double lon, double ele) { 31 32 19 super(lat, lon); 20 this.ele = ele; 33 21 } 34 22 35 23 public EleCoordinate(LatLon latLon, double ele) { 36 this(latLon.lat(), latLon.lon(), ele); 24 this(latLon.lat(), latLon.lon(), ele); 37 25 } 38 26 … … 45 33 return ele; 46 34 } 47 35 36 @Override 48 37 public String toString() { 49 38 return "EleCoordinate[" + lat() + ", " + lon() + ", " + getEle() + "]"; -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/EleVertex.java
r29979 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation.grid; 15 3 … … 30 18 31 19 public EleVertex(EleCoordinate p1, EleCoordinate p2, EleCoordinate p3) { 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 20 points[0] = p1; 21 points[1] = p2; 22 points[2] = p3; 23 24 // compute elevation 25 double z = 0D; 26 boolean eleValid = true; 27 for (EleCoordinate point : points) { 28 if (ElevationHelper.isValidElevation(p1.getEle())) { 29 z += point.getEle(); 30 } else { 31 eleValid = false; 32 break; 33 } 34 } 35 36 if (eleValid) { 37 avrgEle = z / NPOINTS; 38 } else { 39 avrgEle = ElevationHelper.NO_ELEVATION; 40 } 41 42 // compute the (approx.!) area of the vertex using heron's formula 43 double a = p1.greatCircleDistance(p2); 44 double b = p2.greatCircleDistance(p3); 45 double c = p1.greatCircleDistance(p3); 46 47 double s = (a + b + c) / 2D; 48 double sq = s * (s - a) * (s - b) * (s - c); 49 area = Math.sqrt(sq); 62 50 } 63 51 64 52 public List<EleVertex> divide() { 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 53 TriangleEdge[] edges = new TriangleEdge[NPOINTS]; 54 55 int k = 0; 56 for (int i = 0; i < points.length; i++) { 57 EleCoordinate c1 = points[i]; 58 59 for (int j = i + 1; j < points.length; j++) { 60 EleCoordinate c2 = points[j]; 61 62 edges[k++] = new TriangleEdge(i, j, c1.greatCircleDistance(c2)); 63 } 64 } 65 66 /* 67 for (int i = 0; i < edges.length; i++) { 68 TriangleEdge triangleEdge = edges[i]; 69 System.out.println("#" + i + ": " +triangleEdge); 70 }*/ 71 72 // sort by distance 73 Arrays.sort(edges); 74 // pick the longest edge 75 TriangleEdge longest = edges[0]; 76 77 78 //System.out.println("Longest " + longest); 79 EleCoordinate pI = points[longest.getI()]; 80 EleCoordinate pJ = points[longest.getJ()]; 81 EleCoordinate pK = points[longest.getK()]; 82 EleCoordinate newP = getMid(pI, pJ); 83 /* 84 System.out.println(pI); 85 System.out.println(pJ); 86 System.out.println(pK); 87 System.out.println(newP); 88 */ 89 List<EleVertex> res = new ArrayList<EleVertex>(); 90 res.add(new EleVertex(pI, pK, newP)); 91 res.add(new EleVertex(pJ, pK, newP)); 92 93 return res; 106 94 } 107 95 … … 113 101 */ 114 102 public boolean isFinished() { 115 116 117 118 119 120 121 122 123 103 double z = 0D; 104 double avrgEle = getEle(); 105 106 for (EleCoordinate point : points) { 107 z += (avrgEle - point.getEle()) * (avrgEle - point.getEle()); 108 } 109 110 // TODO: Check for proper limit 111 return /*z < 75 || */getArea() < (30 * 30); // = 3 * 25 124 112 } 125 113 … … 130 118 */ 131 119 public double getArea() { 132 120 return area; 133 121 } 134 122 … … 141 129 */ 142 130 public EleCoordinate getMid(EleCoordinate c1, EleCoordinate c2) { 143 144 145 146 147 148 149 150 151 152 153 154 155 131 double x = (c1.getX() + c2.getX()) / 2.0; 132 double y = (c1.getY() + c2.getY()) / 2.0; 133 134 double z = (c1.getEle() + c2.getEle()) / 2.0; 135 if (c1.greatCircleDistance(c2) > MIN_DIST) { 136 double hgtZ = ElevationHelper.getSrtmElevation(new LatLon(y, x)); 137 138 if (ElevationHelper.isValidElevation(hgtZ)) { 139 z = hgtZ; 140 } 141 } 142 143 return new EleCoordinate(y, x, z); 156 144 } 157 145 … … 164 152 */ 165 153 public EleCoordinate get(int index) { 166 167 168 154 if (index < 0 || index >= NPOINTS) throw new IllegalArgumentException("Invalid index: " + index); 155 156 return points[index]; 169 157 } 170 158 … … 176 164 public double getEle() { 177 165 178 166 return avrgEle; 179 167 } 180 168 181 169 @Override 182 170 public String toString() { 183 184 171 return "EleVertex [avrgEle=" + avrgEle + ", area=" + area + ", points=" 172 + Arrays.toString(points) + "]"; 185 173 } 186 174 … … 189 177 190 178 class TriangleEdge implements Comparable<TriangleEdge> { 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 230 231 232 179 private final int i; 180 private final int j; 181 private final double dist; 182 183 public TriangleEdge(int i, int j, double dist) { 184 super(); 185 this.i = i; 186 this.j = j; 187 this.dist = dist; 188 } 189 190 public int getI() { 191 return i; 192 } 193 194 public int getJ() { 195 return j; 196 } 197 198 public int getK() { 199 if (i == 0) { 200 return j == 1 ? 2 : 1; 201 } else if (i == 1) { 202 return j == 0 ? 2 : 0; 203 } else { 204 return j == 0 ? 1 : 0; 205 } 206 } 207 208 public double getDist() { 209 return dist; 210 } 211 212 @Override 213 public int compareTo(TriangleEdge o) { 214 return (int) (o.getDist() - dist); 215 } 216 217 @Override 218 public String toString() { 219 return "TriangleEdge [i=" + i + ", j=" + j + ", dist=" + dist + "]"; 220 } 233 221 } 234 222 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridLayer.java
r29964 r30344 1 /* 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.grid; 16 3 … … 46 33 public class ElevationGridLayer extends Layer implements TileLoaderListener { 47 34 private static final int ELE_ZOOM_LEVEL = 13; 48 private IVertexRenderer vertexRenderer;49 private MemoryTileCache tileCache;35 private final IVertexRenderer vertexRenderer; 36 private final MemoryTileCache tileCache; 50 37 protected TileSource tileSource; 51 38 protected ElevationGridTileLoader tileLoader; 52 39 protected TileController tileController; 53 40 54 41 private Bounds lastBounds; 55 42 private TileSet tileSet; … … 59 46 */ 60 47 public ElevationGridLayer(String name) { 61 super(name); 62 63 setOpacity(0.8); 64 setBackgroundLayer(true); 65 vertexRenderer = new SimpleVertexRenderer(); 66 67 tileCache = new MemoryTileCache(); 68 tileCache.setCacheSize(500); 69 tileSource = new ElevationGridTileSource(name); 70 tileLoader = new ElevationGridTileLoader(this); 71 tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader); 72 } 73 74 /* (non-Javadoc) 75 * @see org.openstreetmap.josm.gui.layer.Layer#paint(java.awt.Graphics2D, org.openstreetmap.josm.gui.MapView, org.openstreetmap.josm.data.Bounds) 76 */ 48 super(name); 49 50 setOpacity(0.8); 51 setBackgroundLayer(true); 52 vertexRenderer = new SimpleVertexRenderer(); 53 54 tileCache = new MemoryTileCache(); 55 tileCache.setCacheSize(500); 56 tileSource = new ElevationGridTileSource(name); 57 tileLoader = new ElevationGridTileLoader(this); 58 tileController = new ElevationGridTileController(tileSource, tileCache, this, tileLoader); 59 } 60 77 61 @Override 78 62 public void paint(Graphics2D g, MapView mv, Bounds box) { 79 boolean needsNewTileSet = tileSet == null || (lastBounds == null || !lastBounds.equals(box)); 80 81 82 83 84 85 86 87 63 boolean needsNewTileSet = tileSet == null || (lastBounds == null || !lastBounds.equals(box)); 64 65 if (needsNewTileSet) { 66 tileSet = new TileSet(box.getMin(), box.getMax(), ELE_ZOOM_LEVEL); // we use a vector format with constant zoom level 67 lastBounds = box; 68 System.out.println("paint " + tileSet); 69 } 70 71 if (tileSet.insane()) { 88 72 myDrawString(g, tr("zoom in to load any tiles"), 120, 120); 89 73 return; … … 95 79 return; 96 80 } 97 98 for(int x = tileSet.x0; x <= tileSet.x1; x++) { 99 for(int y = tileSet.y0; y <= tileSet.y1; y++) { 100 Tile t = tileController.getTile(x, y, ELE_ZOOM_LEVEL); 101 102 if (t != null && t.isLoaded() && t instanceof ElevationGridTile) { 103 ((ElevationGridTile)t).paintTile(g, mv, vertexRenderer); 104 } else { 105 // give some consolation... 106 Point topLeft = mv.getPoint( 107 new LatLon(tileSource.tileYToLat(y, ELE_ZOOM_LEVEL), 108 tileSource.tileXToLon(x, ELE_ZOOM_LEVEL))); 109 t.paint(g, topLeft.x, topLeft.y); 110 } 111 } 112 } 113 } 114 115 116 117 /* (non-Javadoc) 118 * @see org.openstreetmap.josm.gui.layer.Layer#getToolTipText() 119 */ 81 82 for(int x = tileSet.x0; x <= tileSet.x1; x++) { 83 for(int y = tileSet.y0; y <= tileSet.y1; y++) { 84 Tile t = tileController.getTile(x, y, ELE_ZOOM_LEVEL); 85 86 if (t != null && t.isLoaded() && t instanceof ElevationGridTile) { 87 ((ElevationGridTile)t).paintTile(g, mv, vertexRenderer); 88 } else { 89 // give some consolation... 90 Point topLeft = mv.getPoint( 91 new LatLon(tileSource.tileYToLat(y, ELE_ZOOM_LEVEL), 92 tileSource.tileXToLon(x, ELE_ZOOM_LEVEL))); 93 t.paint(g, topLeft.x, topLeft.y); 94 } 95 } 96 } 97 } 98 120 99 @Override 121 100 public String getToolTipText() { 122 // TODO Auto-generated method stub 123 return null; 124 } 125 126 /* (non-Javadoc) 127 * @see org.openstreetmap.josm.gui.layer.Layer#visitBoundingBox(org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor) 128 */ 101 // TODO Auto-generated method stub 102 return null; 103 } 104 129 105 @Override 130 106 public void visitBoundingBox(BoundingXYVisitor v) { 131 // TODO Auto-generated method stub 132 133 } 134 135 /* (non-Javadoc) 136 * @see org.openstreetmap.josm.gui.layer.Layer#getMenuEntries() 137 */ 107 // TODO Auto-generated method stub 108 109 } 110 138 111 @Override 139 112 public Action[] getMenuEntries() { 140 141 142 } 143 113 // TODO Auto-generated method stub 114 return null; 115 } 116 144 117 @Override 145 118 public void tileLoadingFinished(Tile tile, boolean success) { 146 try { 147 //System.out.println("tileLoadingFinished " + tile + ", success = " + success); 148 if (Main.map != null) { 149 Main.map.repaint(100); 150 } 151 } catch(Exception ex) { 152 System.err.println(ex); 153 ex.printStackTrace(System.err); 154 } 119 try { 120 if (Main.map != null) { 121 Main.map.repaint(100); 122 } 123 } catch(Exception ex) { 124 System.err.println(ex); 125 ex.printStackTrace(System.err); 126 } 155 127 } 156 128 157 129 @Override 158 130 public TileCache getTileCache() { 159 // TODO Auto-generated method stub 160 return tileCache; 161 } 162 163 /* (non-Javadoc) 164 * @see org.openstreetmap.josm.gui.layer.Layer#getIcon() 165 */ 166 @Override 167 public Icon getIcon() { 168 return ImageProvider.get("layer", "elevation"); 169 } 170 171 172 /* (non-Javadoc) 173 * @see org.openstreetmap.josm.gui.layer.Layer#mergeFrom(org.openstreetmap.josm.gui.layer.Layer) 174 */ 131 // TODO Auto-generated method stub 132 return tileCache; 133 } 134 135 @Override 136 public Icon getIcon() { 137 return ImageProvider.get("layer", "elevation"); 138 } 139 175 140 @Override 176 141 public void mergeFrom(Layer from) { 177 // TODO Auto-generated method stub 178 179 } 180 181 /* (non-Javadoc) 182 * @see org.openstreetmap.josm.gui.layer.Layer#isMergable(org.openstreetmap.josm.gui.layer.Layer) 183 */ 142 // TODO Auto-generated method stub 143 144 } 145 184 146 @Override 185 147 public boolean isMergable(Layer other) { 186 // TODO Auto-generated method stub 187 return false; 188 } 189 190 /* (non-Javadoc) 191 * @see org.openstreetmap.josm.gui.layer.Layer#getInfoComponent() 192 */ 148 // TODO Auto-generated method stub 149 return false; 150 } 151 193 152 @Override 194 153 public Object getInfoComponent() { 195 196 197 } 198 199 154 // TODO Auto-generated method stub 155 return null; 156 } 157 158 200 159 // Stolen from TMSLayer... 201 160 void myDrawString(Graphics g, String text, int x, int y) { … … 206 165 g.drawString(text,x,y); 207 166 } 208 167 209 168 private class TileSet { 210 169 int x0, x1, y0, y1; … … 246 205 } 247 206 } 248 207 249 208 int size() { 250 209 int x_span = x1 - x0 + 1; … … 253 212 } 254 213 255 256 257 258 259 260 261 262 263 264 265 266 267 268 269 270 271 272 273 274 275 276 214 @Override 215 public String toString() { 216 return "TileSet [x0=" + x0 + ", x1=" + x1 + ", y0=" + y0 + ", y1=" 217 + y1 + ", size()=" + size() + ", tilesSpanned()=" 218 + tilesSpanned() + "]"; 219 } 220 221 double tilesSpanned() { 222 return Math.sqrt(1.0 * this.size()); 223 } 224 225 boolean tooSmall() { 226 return this.tilesSpanned() < 1; 227 } 228 229 boolean tooLarge() { 230 return this.tilesSpanned() > 50; 231 } 232 233 boolean insane() { 234 return this.tilesSpanned() > 200; 235 } 277 236 } 278 237 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTile.java
r29979 r30344 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.plugins.elevation.grid; 2 3 … … 30 31 31 32 public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom) { 32 33 super(source, xtile, ytile, zoom); 33 34 34 35 35 box = tile2Bounds(xtile, ytile, zoom); 36 initQueue(); 36 37 } 37 38 38 39 public ElevationGridTile(TileSource source, int xtile, int ytile, int zoom, 39 40 40 BufferedImage image) { 41 super(source, xtile, ytile, zoom, image); 41 42 42 43 … … 45 46 @Override 46 47 public void loadPlaceholderFromCache(TileCache cache) { 47 48 48 // TODO Auto-generated method stub 49 super.loadPlaceholderFromCache(cache); 49 50 50 51 //System.out.println("loadPlaceholderFromCache"); 51 52 } 52 53 53 54 @Override 54 55 public String getUrl() throws IOException { 55 56 56 // TODO Auto-generated method stub 57 return super.getUrl(); 57 58 } 58 59 … … 62 63 @Override 63 64 public void paint(Graphics g, int x, int y) { 64 65 super.paint(g, x, y); 65 66 66 67 67 //g.drawString(String.format("EGT %d/%d ", getXtile(), getYtile()), x, y); 68 g.drawString(getStatus(), x, y); 68 69 } 69 70 … … 76 77 */ 77 78 public void paintTile(Graphics2D g, MapView mv, IVertexRenderer vertexRenderer) { 78 79 80 81 82 83 79 BlockingDeque<EleVertex> list = getVertices(); 80 for (EleVertex eleVertex : list) { 81 Point p0 = mv.getPoint(eleVertex.get(0)); 82 Point p1 = mv.getPoint(eleVertex.get(1)); 83 Point p2 = mv.getPoint(eleVertex.get(2)); 84 Triangle shape = new Triangle(p0, p1, p2); 84 85 85 86 87 88 89 86 // obtain vertex color 87 g.setColor(vertexRenderer.getElevationColor(eleVertex)); 88 // TODO: Move to renderer 89 g.fill(shape); 90 } 90 91 } 91 92 92 93 @Override 93 94 public void loadImage(InputStream input) throws IOException { 94 95 if (isLoaded()) return; 95 96 96 97 // TODO: Save 97 98 98 99 100 101 99 // We abuse the loadImage method to render the vertices... 100 // 101 while (toDo.size() > 0) { 102 EleVertex vertex = toDo.poll(); 102 103 103 104 105 106 107 108 109 110 111 112 104 if (vertex.isFinished()) { 105 vertices.add(vertex); 106 } else { 107 List<EleVertex> newV = vertex.divide(); 108 for (EleVertex eleVertex : newV) { 109 toDo.add(eleVertex); 110 } 111 } 112 } 113 setLoaded(true); 113 114 } 114 115 115 116 public BlockingDeque<EleVertex> getVertices() { 116 117 return vertices; 117 118 } 118 119 … … 125 126 */ 126 127 private Bounds tile2Bounds(final int x, final int y, final int zoom) { 127 128 129 128 Bounds bb = new Bounds( 129 new LatLon(source.tileYToLat(y, zoom), source.tileXToLon(x, zoom)), 130 new LatLon(source.tileYToLat(y + 1, zoom), source.tileXToLon(x + 1, zoom))); 130 131 131 132 return bb; 132 133 } 133 134 … … 136 137 */ 137 138 private void initQueue() { 138 139 139 LatLon min = box.getMin(); 140 LatLon max = box.getMax(); 140 141 141 142 143 142 // compute missing coordinates 143 LatLon h1 = new LatLon(min.lat(), max.lon()); 144 LatLon h2 = new LatLon(max.lat(), min.lon()); 144 145 145 146 146 double eleMin = ElevationHelper.getSrtmElevation(min); 147 double eleMax = ElevationHelper.getSrtmElevation(max); 147 148 148 149 150 151 152 149 // SRTM files present? 150 if (!ElevationHelper.isValidElevation(eleMax) || !ElevationHelper.isValidElevation(eleMin)) { 151 setError(tr("No SRTM data")); 152 return; 153 } 153 154 154 155 156 157 158 155 // compute elevation coords 156 EleCoordinate p0 = new EleCoordinate(min, eleMin); 157 EleCoordinate p1 = new EleCoordinate(h1, ElevationHelper.getSrtmElevation(h1)); 158 EleCoordinate p2 = new EleCoordinate(max, eleMax); 159 EleCoordinate p3 = new EleCoordinate(h2, ElevationHelper.getSrtmElevation(h2)); 159 160 160 161 162 163 164 165 161 // compute initial vertices 162 EleVertex v1 = new EleVertex(p0, p1, p2); 163 EleVertex v2 = new EleVertex(p2, p3, p0); 164 // enqueue vertices 165 toDo.add(v1); 166 toDo.add(v2); 166 167 } 167 168 168 169 @Override 169 170 public String toString() { 170 171 171 return "ElevationGridTile [box=" + box + ", xtile=" + xtile 172 + ", ytile=" + ytile + "]"; 172 173 } 173 174 -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileController.java
r29964 r30344 1 /* 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.grid; 16 3 … … 29 16 */ 30 17 public class ElevationGridTileController extends TileController { 31 private JobDispatcher jobDispatcher; // is private and no getter32 18 private final JobDispatcher jobDispatcher; // is private and no getter 19 33 20 /** 34 21 * @param source … … 37 24 */ 38 25 public ElevationGridTileController(TileSource source, TileCache tileCache, 39 40 41 42 tileSource = source; // FIXME: hard-coded in base class (although parameter is given)!! 43 44 26 TileLoaderListener listener, TileLoader loader) { 27 super(source, tileCache, listener); 28 29 tileSource = source; // FIXME: hard-coded in base class (although parameter is given)!! 30 tileLoader = loader; // FIXME: hard-coded in base class! 31 jobDispatcher = JobDispatcher.getInstance(); 45 32 } 46 47 /* (non-Javadoc) 48 * @see org.openstreetmap.gui.jmapviewer.TileController#getTile(int, int, int) 49 */ 33 34 @Override 50 35 public Tile getTile(int tilex, int tiley, int zoom) { 51 36 int max = (1 << zoom); … … 54 39 Tile tile = tileCache.getTile(tileSource, tilex, tiley, zoom); 55 40 if (tile == null) { 56 // FIXME: Provide/use a factory method here 41 // FIXME: Provide/use a factory method here 57 42 tile = new ElevationGridTile(tileSource, tilex, tiley, zoom); 58 43 tileCache.addTile(tile); … … 67 52 return tile; 68 53 } 69 54 70 55 /** 71 * 72 */ 73 public void cancelOutstandingJobs() { 74 super.cancelOutstandingJobs(); // should not make a difference but you never know... 75 jobDispatcher.cancelOutstandingJobs(); 76 } 56 * 57 */ 58 @Override 59 public void cancelOutstandingJobs() { 60 super.cancelOutstandingJobs(); // should not make a difference but you never know... 61 jobDispatcher.cancelOutstandingJobs(); 62 } 77 63 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileLoader.java
r29964 r30344 1 /* 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.grid; 16 3 … … 29 16 30 17 public ElevationGridTileLoader(TileLoaderListener listener) { 31 18 CheckParameterUtil.ensureParameterNotNull(listener); 32 19 this.listener = listener; 33 20 } 34 21 35 /* (non-Javadoc)36 * @see org.openstreetmap.gui.jmapviewer.interfaces.TileLoader#createTileLoaderJob(org.openstreetmap.gui.jmapviewer.Tile)37 */38 22 @Override 39 23 public TileJob createTileLoaderJob(final Tile tile) { 40 CheckParameterUtil.ensureParameterNotNull(tile); 41 42 return new TileJob() { 24 CheckParameterUtil.ensureParameterNotNull(tile); 43 25 26 return new TileJob() { 27 28 @Override 44 29 public void run() { 45 30 synchronized (tile) { … … 54 39 } catch (Exception e) { 55 40 tile.setError(e.getMessage()); 56 listener.tileLoadingFinished(tile, false); 41 listener.tileLoadingFinished(tile, false); 57 42 } finally { 58 43 tile.finishLoading(); … … 60 45 } 61 46 47 @Override 62 48 public Tile getTile() { 63 49 return tile; … … 65 51 }; 66 52 } 67 53 68 54 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/ElevationGridTileSource.java
r29964 r30344 1 /* 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.grid; 16 3 … … 25 12 public class ElevationGridTileSource extends AbstractTMSTileSource { 26 13 public ElevationGridTileSource(String name) { 27 28 14 super(name, ""); 15 // TODO Auto-generated constructor stub 29 16 } 30 17 31 18 @Override 32 19 public TileUpdate getTileUpdate() { 33 20 return TileUpdate.None; 34 21 } 35 22 36 23 @Override 37 24 public String getName() { 38 25 return "eg"; 39 26 } 40 27 28 @Override 41 29 public String getExtension() { 42 30 return ""; … … 46 34 * @throws IOException when subclass cannot return the tile URL 47 35 */ 36 @Override 48 37 public String getTilePath(int zoom, int tilex, int tiley) throws IOException { 49 38 return "/" + zoom + "/" + tilex + "/" + tiley + "." + getExtension(); 50 39 } 51 40 41 @Override 52 42 public String getBaseUrl() { 53 43 return ""; … … 71 61 @Override 72 62 public int getTileSize() { 73 63 // TODO 74 64 return 256; 75 65 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/grid/SimpleVertexRenderer.java
r29964 r30344 1 /* 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.grid; 16 3 … … 26 13 public class SimpleVertexRenderer implements IVertexRenderer { 27 14 private ColorMap cMap = null; 28 15 29 16 /** 30 17 * 31 18 */ 32 19 public SimpleVertexRenderer() { 33 20 cMap = ColorMap.getMap(ColorMap.getNames()[0]); 34 21 } 35 22 36 23 @Override 37 24 public Color getElevationColor(EleVertex vertex) { 38 25 return cMap.getColor((int) vertex.getEle()); 39 26 } 40 27 … … 42 29 @Override 43 30 public void selectColorMap(String name) { 44 45 31 // TODO Auto-generated method stub 32 46 33 } 47 34 48 35 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java
r29960 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 40 27 41 28 /** 42 * Provides default rendering for elevation profile layer. 29 * Provides default rendering for elevation profile layer. 43 30 * @author Oliver Wieland <oliver.wieland@online.de> 44 31 */ 45 32 public class DefaultElevationProfileRenderer implements 46 IElevationProfileRenderer { 47 48 private static final int ROUND_RECT_RADIUS = 6; 49 /** 50 * 51 */ 52 private static final int TRIANGLE_BASESIZE = 24; 53 /** 54 * 55 */ 56 private static final int BASIC_WPT_RADIUS = 1; 57 private static final int BIG_WPT_RADIUS = BASIC_WPT_RADIUS * 16; 58 59 // predefined colors 60 private static final Color HIGH_COLOR = ElevationColors.EPMidBlue; 61 private static final Color LOW_COLOR = ElevationColors.EPMidBlue; 62 private static final Color START_COLOR = Color.GREEN; 63 private static final Color END_POINT = Color.RED; 64 private static final Color LEVEL_GAIN_COLOR = Color.GREEN; 65 private static final Color LEVEL_LOSS_COLOR = Color.RED; 66 private static final Color MARKER_POINT = Color.YELLOW; 67 // Predefined radians 68 private static final double RAD_180 = Math.PI; 69 // private static final double RAD_270 = Math.PI * 1.5; 70 private static final double RAD_90 = Math.PI * 0.5; 71 72 private List<Rectangle> forbiddenRects = new ArrayList<Rectangle>(); 73 74 /* 75 * (non-Javadoc) 76 * 77 * @see 78 * org.openstreetmap.josm.plugins.elevation.gui.IElevationProfileRenderer 79 * #getColorForWaypoint 80 * (org.openstreetmap.josm.plugins.elevation.IElevationProfile, 81 * org.openstreetmap.josm.data.gpx.WayPoint, 82 * org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind) 83 */ 84 public Color getColorForWaypoint(IElevationProfile profile, WayPoint wpt, 85 ElevationWayPointKind kind) { 86 87 if (wpt == null || profile == null) { 88 System.err.println(String.format( 89 "Cannot determine color: prof=%s, wpt=%s", profile, wpt)); 90 return null; 91 } 92 93 switch (kind) { 94 case Plain: 95 return Color.LIGHT_GRAY; 96 case ElevationLevelLoss: 97 return LEVEL_LOSS_COLOR; 98 case ElevationLevelGain: 99 return LEVEL_GAIN_COLOR; 100 case Highlighted: 101 return Color.ORANGE; 102 case ElevationGainHigh: 103 return Color.getHSBColor(0.3f, 1.0f, 1.0f); // green 104 case ElevationLossHigh: 105 return Color.getHSBColor(0, 1.0f, 1.0f); // red 106 case ElevationGainLow: 107 return Color.getHSBColor(0.3f, 0.5f, 1.0f); // green with low sat 108 case ElevationLossLow: 109 return Color.getHSBColor(0, 0.5f, 1.0f); // red with low sat 110 case FullHour: 111 return MARKER_POINT; 112 case MaxElevation: 113 return HIGH_COLOR; 114 case MinElevation: 115 return LOW_COLOR; 116 case StartPoint: 117 return START_COLOR; 118 case EndPoint: 119 return END_POINT; 120 default: 121 break; 122 } 123 124 throw new RuntimeException("Unknown way point kind: " + kind); 125 } 126 127 /* 128 * (non-Javadoc) 129 * 130 * @see 131 * org.openstreetmap.josm.plugins.elevation.gui.IElevationProfileRenderer 132 * #renderWayPoint(java.awt.Graphics, 133 * org.openstreetmap.josm.plugins.elevation.IElevationProfile, 134 * org.openstreetmap.josm.data.gpx.WayPoint, 135 * org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind) 136 */ 137 public void renderWayPoint(Graphics g, IElevationProfile profile, 138 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 139 140 CheckParameterUtil.ensureParameterNotNull(g, "graphics"); 141 CheckParameterUtil.ensureParameterNotNull(profile, "profile"); 142 CheckParameterUtil.ensureParameterNotNull(mv, "map view"); 143 144 if (wpt == null) { 145 System.err.println(String.format( 146 "Cannot paint: mv=%s, prof=%s, wpt=%s", mv, profile, wpt)); 147 return; 148 } 149 150 switch (kind) { 151 case MinElevation: 152 case MaxElevation: 153 renderMinMaxPoint(g, profile, mv, wpt, kind); 154 break; 155 case EndPoint: 156 case StartPoint: 157 renderStartEndPoint(g, profile, mv, wpt, kind); 158 break; 159 default: 160 renderRegularWayPoint(g, profile, mv, wpt, kind); 161 break; 162 } 163 } 164 165 /* (non-Javadoc) 166 * @see org.openstreetmap.josm.plugins.elevation.gui.IElevationProfileRenderer#renderWayPoints(java.awt.Graphics, org.openstreetmap.josm.plugins.elevation.gpx.IElevationProfile, org.openstreetmap.josm.gui.MapView, org.openstreetmap.josm.data.gpx.WayPoint, org.openstreetmap.josm.data.gpx.WayPoint) 167 */ 168 @Override 169 public void renderLine(Graphics g, IElevationProfile profile, 170 MapView mv, WayPoint wpt1, WayPoint wpt2, ElevationWayPointKind kind) { 171 172 CheckParameterUtil.ensureParameterNotNull(g, "graphics"); 173 CheckParameterUtil.ensureParameterNotNull(profile, "profile"); 174 CheckParameterUtil.ensureParameterNotNull(mv, "map view"); 175 176 if (wpt1 == null || wpt2 == null) { 177 System.err.println(String.format( 178 "Cannot paint line: mv=%s, prof=%s, kind = %s", mv, profile, kind)); 179 return; 180 } 181 182 // obtain and set color 183 g.setColor(getColorForWaypoint(profile, wpt2, kind)); 184 185 // transform to view 186 Point pnt1 = mv.getPoint(wpt1.getEastNorth()); 187 Point pnt2 = mv.getPoint(wpt2.getEastNorth()); 188 189 // use thick line, if possible 190 if (g instanceof Graphics2D) { 191 Graphics2D g2 = (Graphics2D) g; 192 Stroke oldS = g2.getStroke(); 193 try { 194 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 195 g2.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y); 196 } finally { 197 // must be restored; otherwise other layers may using this style, too 198 g2.setStroke(oldS); 199 } 200 } else { 201 // only poor man's graphics 202 g.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y); 203 } 204 } 205 206 /** 207 * Renders a regular way point. 208 * 209 * @param g 210 * The graphics context. 211 * @param profile 212 * The elevation profile. 213 * @param mv 214 * The map view instance. 215 * @param wpt 216 * The way point to render. 217 * @param kind 218 * The way point kind (start, end, max,...). 219 */ 220 private void renderRegularWayPoint(Graphics g, IElevationProfile profile, 221 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 222 223 Color c = getColorForWaypoint(profile, wpt, kind); 224 Point pnt = mv.getPoint(wpt.getEastNorth()); 225 226 /* Paint full hour label */ 227 if (kind == ElevationWayPointKind.FullHour) { 228 int hour = ElevationHelper.getHourOfWayPoint(wpt); 229 drawLabel(String.format("%02d:00", hour), pnt.x, pnt.y 230 + g.getFontMetrics().getHeight(), g); 231 } 232 233 /* Paint label for elevation levels */ 234 if (kind == ElevationWayPointKind.ElevationLevelGain || kind == ElevationWayPointKind.ElevationLevelLoss) { 235 int ele = ((int) Math.rint(ElevationHelper.getElevation(wpt) / 100.0)) * 100; 236 drawLabelWithTriangle(ElevationHelper.getElevationText(ele), pnt.x, pnt.y 237 + g.getFontMetrics().getHeight(), g, Color.darkGray, 8, 238 getColorForWaypoint(profile, wpt, kind), 239 kind == ElevationWayPointKind.ElevationLevelGain ? TriangleDir.Up : TriangleDir.Down); 240 } 241 242 /* Paint cursor labels */ 243 if (kind == ElevationWayPointKind.Highlighted) { 244 drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS); 245 drawLabel(ElevationHelper.getTimeText(wpt), pnt.x, pnt.y 246 - g.getFontMetrics().getHeight() - 5, g); 247 drawLabel(ElevationHelper.getElevationText(wpt), pnt.x, pnt.y 248 + g.getFontMetrics().getHeight() + 5, g); 249 } 250 } 251 252 /** 253 * Renders a min/max point 254 * 255 * @param g 256 * The graphics context. 257 * @param profile 258 * The elevation profile. 259 * @param mv 260 * The map view instance. 261 * @param wpt 262 * The way point to render. 263 * @param kind 264 * The way point kind (start, end, max,...). 265 */ 266 private void renderMinMaxPoint(Graphics g, IElevationProfile profile, 267 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 268 269 Color c = getColorForWaypoint(profile, wpt, kind); 270 int eleH = (int) ElevationHelper.getElevation(wpt); 271 Point pnt = mv.getPoint(wpt.getEastNorth()); 272 273 TriangleDir td = TriangleDir.Up; 274 275 switch (kind) { 276 case MaxElevation: 277 td = TriangleDir.Up; 278 break; 279 case MinElevation: 280 td = TriangleDir.Down; 281 break; 282 case EndPoint: 283 td = TriangleDir.Left; 284 break; 285 case StartPoint: 286 td = TriangleDir.Right; 287 break; 288 default: 289 return; // nothing to do 290 } 291 292 drawRegularTriangle(g, c, td, pnt.x, pnt.y, 293 DefaultElevationProfileRenderer.TRIANGLE_BASESIZE); 294 295 drawLabel(ElevationHelper.getElevationText(eleH), pnt.x, pnt.y 296 + g.getFontMetrics().getHeight(), g, c); 297 } 298 299 /** 300 * Draws a regular triangle. 301 * 302 * @param g 303 * The graphics context. 304 * @param c 305 * The fill color of the triangle. 306 * @param dir 307 * The direction of the triangle 308 * @param x 309 * The x coordinate in the graphics context. 310 * @param y 311 * The y coordinate in the graphics context. 312 * @param baseLength 313 * The side length in pixel of the triangle. 314 */ 315 private void drawRegularTriangle(Graphics g, Color c, TriangleDir dir, 316 int x, int y, int baseLength) { 317 if (baseLength < 2) 318 return; // cannot render triangle 319 320 int b2 = baseLength >> 1; 321 322 // coordinates for upwards directed triangle 323 Point p[] = new Point[3]; 324 325 for (int i = 0; i < p.length; i++) { 326 p[i] = new Point(); 327 } 328 329 p[0].x = -b2; 330 p[0].y = b2; 331 332 p[1].x = b2; 333 p[1].y = b2; 334 335 p[2].x = 0; 336 p[2].y = -b2; 337 338 Triangle t = new Triangle(p[0], p[1], p[2]); 339 340 // rotation angle in rad 341 double theta = 0.0; 342 343 switch (dir) { 344 case Up: 345 theta = 0.0; 346 break; 347 case Down: 348 theta = RAD_180; 349 break; 350 case Left: 351 theta = -RAD_90; 352 break; 353 case Right: 354 theta = RAD_90; 355 break; 356 } 357 358 // rotate shape 359 AffineTransform at = AffineTransform.getRotateInstance(theta); 360 Shape tRot = at.createTransformedShape(t); 361 // translate shape 362 AffineTransform at2 = AffineTransform.getTranslateInstance(x, y); 363 Shape ts = at2.createTransformedShape(tRot); 364 365 // draw the shape 366 Graphics2D g2 = (Graphics2D) g; 367 if (g2 != null) { 368 Color oldC = g2.getColor(); 369 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 370 RenderingHints.VALUE_ANTIALIAS_ON); 371 g2.setColor(c); 372 g2.fill(ts); 373 g2.setColor(oldC); 374 } 375 } 376 377 /** 378 * Renders a start/end point. 379 * 380 * @param g 381 * The graphics context. 382 * @param profile 383 * The elevation profile. 384 * @param mv 385 * The map view instance. 386 * @param wpt 387 * The way point to render. 388 * @param kind 389 * The way point kind (start, end, max,...). 390 */ 391 private void renderStartEndPoint(Graphics g, IElevationProfile profile, 392 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 393 394 Color c = getColorForWaypoint(profile, wpt, kind); 395 Point pnt = mv.getPoint(wpt.getEastNorth()); 396 drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS); 397 } 398 399 /** 400 * Draws a shaded sphere. 401 * 402 * @param g 403 * The graphics context. 404 * @param firstCol 405 * The focus color (usually white). 406 * @param secondCol 407 * The sphere color. 408 * @param x 409 * The x coordinate of the sphere center. 410 * @param y 411 * The y coordinate of the sphere center. 412 * @param radius 413 * The radius of the sphere. 414 */ 415 private void drawSphere(Graphics g, Color firstCol, Color secondCol, int x, 416 int y, int radius) { 417 Point2D center = new Point2D.Float(x, y); 418 Point2D focus = new Point2D.Float(x - (radius * 0.6f), y 419 - (radius * 0.6f)); 420 float[] dist = { 0.1f, 0.2f, 1.0f }; 421 Color[] colors = { firstCol, secondCol, Color.DARK_GRAY }; 422 RadialGradientPaint p = new RadialGradientPaint(center, radius, focus, 423 dist, colors, CycleMethod.NO_CYCLE); 424 425 Graphics2D g2 = (Graphics2D) g; 426 if (g2 != null) { 427 g2.setPaint(p); 428 int r2 = radius / 2; 429 g2.fillOval(x - r2, y - r2, radius, radius); 430 } 431 } 432 433 /** 434 * Draws a label within a filled rounded rectangle with standard gradient colors. 435 * 436 * @param s 437 * The text to draw. 438 * @param x 439 * The x coordinate of the label. 440 * @param y 441 * The y coordinate of the label. 442 * @param g 443 * The graphics context. 444 */ 445 private void drawLabel(String s, int x, int y, Graphics g) { 446 drawLabel(s, x, y, g, Color.GRAY); 447 } 448 449 /** 450 * Draws a label within a filled rounded rectangle with the specified second gradient color (first color is <tt>Color.WHITE<tt>). 451 * 452 * @param s 453 * The text to draw. 454 * @param x 455 * The x coordinate of the label. 456 * @param y 457 * The y coordinate of the label. 458 * @param g 459 * The graphics context. 460 * @param secondGradColor 461 * The second color of the gradient. 462 */ 463 private void drawLabel(String s, int x, int y, Graphics g, 464 Color secondGradColor) { 465 Graphics2D g2d = (Graphics2D) g; 466 467 int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10; 468 int height = g.getFont().getSize() + g.getFontMetrics().getLeading() 469 + 5; 470 471 Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, 472 height); 473 474 if (isForbiddenArea(r)) { 475 return; // no space left, skip this label 476 } 477 478 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 479 RenderingHints.VALUE_ANTIALIAS_ON); 480 GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y 481 + (height / 2), secondGradColor, false); 482 g2d.setPaint(gradient); 483 484 g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 485 ROUND_RECT_RADIUS); 486 487 g2d.setColor(Color.BLACK); 488 489 g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 490 ROUND_RECT_RADIUS); 491 g2d.drawString(s, x - (width / 2) + 5, y + (height / 2) - 3); 492 493 forbiddenRects.add(r); 494 } 495 496 /** 497 * Draws a label with an additional triangle on the left side. 498 * 499 * @param s 500 * The text to draw. 501 * @param x 502 * The x coordinate of the label. 503 * @param y 504 * The y coordinate of the label. 505 * @param g 506 * The graphics context. 507 * @param secondGradColor 508 * The second color of the gradient. 509 * @param baseLength 510 * The base length of the triangle in pixels. 511 * @param triangleColor 512 * The color of the triangle. 513 * @param triangleDir 514 * The direction of the triangle. 515 */ 516 private void drawLabelWithTriangle(String s, int x, int y, Graphics g, 517 Color secondGradColor, int baseLength, Color triangleColor, 518 TriangleDir triangleDir) { 519 Graphics2D g2d = (Graphics2D) g; 520 521 int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10 + baseLength + 5; 522 int height = g.getFont().getSize() + g.getFontMetrics().getLeading() + 5; 523 524 Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, height); 525 526 if (isForbiddenArea(r)) { 527 return; // no space left, skip this label 528 } 529 530 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 531 RenderingHints.VALUE_ANTIALIAS_ON); 532 GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y 533 + (height / 2), secondGradColor, false); 534 g2d.setPaint(gradient); 535 536 g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 537 ROUND_RECT_RADIUS); 538 539 g2d.setColor(Color.BLACK); 540 541 g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 542 ROUND_RECT_RADIUS); 543 g2d.drawString(s, x - (width / 2) + 8 + baseLength, y + (height / 2) - 3); 544 drawRegularTriangle(g2d, triangleColor, triangleDir, r.x + baseLength, 545 r.y + baseLength, baseLength); 546 547 forbiddenRects.add(r); 548 } 549 550 /** 551 * Checks, if the rectangle has been 'reserved' by an previous draw action. 552 * 553 * @param r 554 * The area to check for. 555 * @return true, if area is already occupied by another rectangle. 556 */ 557 private boolean isForbiddenArea(Rectangle r) { 558 559 for (Rectangle rTest : forbiddenRects) { 560 if (r.intersects(rTest)) 561 return true; 562 } 563 return false; 564 } 565 566 @Override 567 public void beginRendering() { 568 forbiddenRects.clear(); 569 } 570 571 @Override 572 public void finishRendering() { 573 // nothing to do currently 574 } 575 576 33 IElevationProfileRenderer { 34 35 private static final int ROUND_RECT_RADIUS = 6; 36 /** 37 * 38 */ 39 private static final int TRIANGLE_BASESIZE = 24; 40 /** 41 * 42 */ 43 private static final int BASIC_WPT_RADIUS = 1; 44 private static final int BIG_WPT_RADIUS = BASIC_WPT_RADIUS * 16; 45 46 // predefined colors 47 private static final Color HIGH_COLOR = ElevationColors.EPMidBlue; 48 private static final Color LOW_COLOR = ElevationColors.EPMidBlue; 49 private static final Color START_COLOR = Color.GREEN; 50 private static final Color END_POINT = Color.RED; 51 private static final Color LEVEL_GAIN_COLOR = Color.GREEN; 52 private static final Color LEVEL_LOSS_COLOR = Color.RED; 53 private static final Color MARKER_POINT = Color.YELLOW; 54 // Predefined radians 55 private static final double RAD_180 = Math.PI; 56 // private static final double RAD_270 = Math.PI * 1.5; 57 private static final double RAD_90 = Math.PI * 0.5; 58 59 private final List<Rectangle> forbiddenRects = new ArrayList<Rectangle>(); 60 61 @Override 62 public Color getColorForWaypoint(IElevationProfile profile, WayPoint wpt, 63 ElevationWayPointKind kind) { 64 65 if (wpt == null || profile == null) { 66 System.err.println(String.format( 67 "Cannot determine color: prof=%s, wpt=%s", profile, wpt)); 68 return null; 69 } 70 71 switch (kind) { 72 case Plain: 73 return Color.LIGHT_GRAY; 74 case ElevationLevelLoss: 75 return LEVEL_LOSS_COLOR; 76 case ElevationLevelGain: 77 return LEVEL_GAIN_COLOR; 78 case Highlighted: 79 return Color.ORANGE; 80 case ElevationGainHigh: 81 return Color.getHSBColor(0.3f, 1.0f, 1.0f); // green 82 case ElevationLossHigh: 83 return Color.getHSBColor(0, 1.0f, 1.0f); // red 84 case ElevationGainLow: 85 return Color.getHSBColor(0.3f, 0.5f, 1.0f); // green with low sat 86 case ElevationLossLow: 87 return Color.getHSBColor(0, 0.5f, 1.0f); // red with low sat 88 case FullHour: 89 return MARKER_POINT; 90 case MaxElevation: 91 return HIGH_COLOR; 92 case MinElevation: 93 return LOW_COLOR; 94 case StartPoint: 95 return START_COLOR; 96 case EndPoint: 97 return END_POINT; 98 default: 99 break; 100 } 101 102 throw new RuntimeException("Unknown way point kind: " + kind); 103 } 104 105 @Override 106 public void renderWayPoint(Graphics g, IElevationProfile profile, 107 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 108 109 CheckParameterUtil.ensureParameterNotNull(g, "graphics"); 110 CheckParameterUtil.ensureParameterNotNull(profile, "profile"); 111 CheckParameterUtil.ensureParameterNotNull(mv, "map view"); 112 113 if (wpt == null) { 114 System.err.println(String.format( 115 "Cannot paint: mv=%s, prof=%s, wpt=%s", mv, profile, wpt)); 116 return; 117 } 118 119 switch (kind) { 120 case MinElevation: 121 case MaxElevation: 122 renderMinMaxPoint(g, profile, mv, wpt, kind); 123 break; 124 case EndPoint: 125 case StartPoint: 126 renderStartEndPoint(g, profile, mv, wpt, kind); 127 break; 128 default: 129 renderRegularWayPoint(g, profile, mv, wpt, kind); 130 break; 131 } 132 } 133 134 @Override 135 public void renderLine(Graphics g, IElevationProfile profile, 136 MapView mv, WayPoint wpt1, WayPoint wpt2, ElevationWayPointKind kind) { 137 138 CheckParameterUtil.ensureParameterNotNull(g, "graphics"); 139 CheckParameterUtil.ensureParameterNotNull(profile, "profile"); 140 CheckParameterUtil.ensureParameterNotNull(mv, "map view"); 141 142 if (wpt1 == null || wpt2 == null) { 143 System.err.println(String.format( 144 "Cannot paint line: mv=%s, prof=%s, kind = %s", mv, profile, kind)); 145 return; 146 } 147 148 // obtain and set color 149 g.setColor(getColorForWaypoint(profile, wpt2, kind)); 150 151 // transform to view 152 Point pnt1 = mv.getPoint(wpt1.getEastNorth()); 153 Point pnt2 = mv.getPoint(wpt2.getEastNorth()); 154 155 // use thick line, if possible 156 if (g instanceof Graphics2D) { 157 Graphics2D g2 = (Graphics2D) g; 158 Stroke oldS = g2.getStroke(); 159 try { 160 g2.setStroke(new BasicStroke(3, BasicStroke.CAP_ROUND, BasicStroke.JOIN_ROUND)); 161 g2.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y); 162 } finally { 163 // must be restored; otherwise other layers may using this style, too 164 g2.setStroke(oldS); 165 } 166 } else { 167 // only poor man's graphics 168 g.drawLine(pnt1.x, pnt1.y, pnt2.x, pnt2.y); 169 } 170 } 171 172 /** 173 * Renders a regular way point. 174 * 175 * @param g 176 * The graphics context. 177 * @param profile 178 * The elevation profile. 179 * @param mv 180 * The map view instance. 181 * @param wpt 182 * The way point to render. 183 * @param kind 184 * The way point kind (start, end, max,...). 185 */ 186 private void renderRegularWayPoint(Graphics g, IElevationProfile profile, 187 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 188 189 Color c = getColorForWaypoint(profile, wpt, kind); 190 Point pnt = mv.getPoint(wpt.getEastNorth()); 191 192 /* Paint full hour label */ 193 if (kind == ElevationWayPointKind.FullHour) { 194 int hour = ElevationHelper.getHourOfWayPoint(wpt); 195 drawLabel(String.format("%02d:00", hour), pnt.x, pnt.y 196 + g.getFontMetrics().getHeight(), g); 197 } 198 199 /* Paint label for elevation levels */ 200 if (kind == ElevationWayPointKind.ElevationLevelGain || kind == ElevationWayPointKind.ElevationLevelLoss) { 201 int ele = ((int) Math.rint(ElevationHelper.getElevation(wpt) / 100.0)) * 100; 202 drawLabelWithTriangle(ElevationHelper.getElevationText(ele), pnt.x, pnt.y 203 + g.getFontMetrics().getHeight(), g, Color.darkGray, 8, 204 getColorForWaypoint(profile, wpt, kind), 205 kind == ElevationWayPointKind.ElevationLevelGain ? TriangleDir.Up : TriangleDir.Down); 206 } 207 208 /* Paint cursor labels */ 209 if (kind == ElevationWayPointKind.Highlighted) { 210 drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS); 211 drawLabel(ElevationHelper.getTimeText(wpt), pnt.x, pnt.y 212 - g.getFontMetrics().getHeight() - 5, g); 213 drawLabel(ElevationHelper.getElevationText(wpt), pnt.x, pnt.y 214 + g.getFontMetrics().getHeight() + 5, g); 215 } 216 } 217 218 /** 219 * Renders a min/max point 220 * 221 * @param g 222 * The graphics context. 223 * @param profile 224 * The elevation profile. 225 * @param mv 226 * The map view instance. 227 * @param wpt 228 * The way point to render. 229 * @param kind 230 * The way point kind (start, end, max,...). 231 */ 232 private void renderMinMaxPoint(Graphics g, IElevationProfile profile, 233 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 234 235 Color c = getColorForWaypoint(profile, wpt, kind); 236 int eleH = (int) ElevationHelper.getElevation(wpt); 237 Point pnt = mv.getPoint(wpt.getEastNorth()); 238 239 TriangleDir td = TriangleDir.Up; 240 241 switch (kind) { 242 case MaxElevation: 243 td = TriangleDir.Up; 244 break; 245 case MinElevation: 246 td = TriangleDir.Down; 247 break; 248 case EndPoint: 249 td = TriangleDir.Left; 250 break; 251 case StartPoint: 252 td = TriangleDir.Right; 253 break; 254 default: 255 return; // nothing to do 256 } 257 258 drawRegularTriangle(g, c, td, pnt.x, pnt.y, 259 DefaultElevationProfileRenderer.TRIANGLE_BASESIZE); 260 261 drawLabel(ElevationHelper.getElevationText(eleH), pnt.x, pnt.y 262 + g.getFontMetrics().getHeight(), g, c); 263 } 264 265 /** 266 * Draws a regular triangle. 267 * 268 * @param g 269 * The graphics context. 270 * @param c 271 * The fill color of the triangle. 272 * @param dir 273 * The direction of the triangle 274 * @param x 275 * The x coordinate in the graphics context. 276 * @param y 277 * The y coordinate in the graphics context. 278 * @param baseLength 279 * The side length in pixel of the triangle. 280 */ 281 private void drawRegularTriangle(Graphics g, Color c, TriangleDir dir, 282 int x, int y, int baseLength) { 283 if (baseLength < 2) 284 return; // cannot render triangle 285 286 int b2 = baseLength >> 1; 287 288 // coordinates for upwards directed triangle 289 Point p[] = new Point[3]; 290 291 for (int i = 0; i < p.length; i++) { 292 p[i] = new Point(); 293 } 294 295 p[0].x = -b2; 296 p[0].y = b2; 297 298 p[1].x = b2; 299 p[1].y = b2; 300 301 p[2].x = 0; 302 p[2].y = -b2; 303 304 Triangle t = new Triangle(p[0], p[1], p[2]); 305 306 // rotation angle in rad 307 double theta = 0.0; 308 309 switch (dir) { 310 case Up: 311 theta = 0.0; 312 break; 313 case Down: 314 theta = RAD_180; 315 break; 316 case Left: 317 theta = -RAD_90; 318 break; 319 case Right: 320 theta = RAD_90; 321 break; 322 } 323 324 // rotate shape 325 AffineTransform at = AffineTransform.getRotateInstance(theta); 326 Shape tRot = at.createTransformedShape(t); 327 // translate shape 328 AffineTransform at2 = AffineTransform.getTranslateInstance(x, y); 329 Shape ts = at2.createTransformedShape(tRot); 330 331 // draw the shape 332 Graphics2D g2 = (Graphics2D) g; 333 if (g2 != null) { 334 Color oldC = g2.getColor(); 335 g2.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 336 RenderingHints.VALUE_ANTIALIAS_ON); 337 g2.setColor(c); 338 g2.fill(ts); 339 g2.setColor(oldC); 340 } 341 } 342 343 /** 344 * Renders a start/end point. 345 * 346 * @param g 347 * The graphics context. 348 * @param profile 349 * The elevation profile. 350 * @param mv 351 * The map view instance. 352 * @param wpt 353 * The way point to render. 354 * @param kind 355 * The way point kind (start, end, max,...). 356 */ 357 private void renderStartEndPoint(Graphics g, IElevationProfile profile, 358 MapView mv, WayPoint wpt, ElevationWayPointKind kind) { 359 360 Color c = getColorForWaypoint(profile, wpt, kind); 361 Point pnt = mv.getPoint(wpt.getEastNorth()); 362 drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS); 363 } 364 365 /** 366 * Draws a shaded sphere. 367 * 368 * @param g 369 * The graphics context. 370 * @param firstCol 371 * The focus color (usually white). 372 * @param secondCol 373 * The sphere color. 374 * @param x 375 * The x coordinate of the sphere center. 376 * @param y 377 * The y coordinate of the sphere center. 378 * @param radius 379 * The radius of the sphere. 380 */ 381 private void drawSphere(Graphics g, Color firstCol, Color secondCol, int x, 382 int y, int radius) { 383 Point2D center = new Point2D.Float(x, y); 384 Point2D focus = new Point2D.Float(x - (radius * 0.6f), y 385 - (radius * 0.6f)); 386 float[] dist = { 0.1f, 0.2f, 1.0f }; 387 Color[] colors = { firstCol, secondCol, Color.DARK_GRAY }; 388 RadialGradientPaint p = new RadialGradientPaint(center, radius, focus, 389 dist, colors, CycleMethod.NO_CYCLE); 390 391 Graphics2D g2 = (Graphics2D) g; 392 if (g2 != null) { 393 g2.setPaint(p); 394 int r2 = radius / 2; 395 g2.fillOval(x - r2, y - r2, radius, radius); 396 } 397 } 398 399 /** 400 * Draws a label within a filled rounded rectangle with standard gradient colors. 401 * 402 * @param s 403 * The text to draw. 404 * @param x 405 * The x coordinate of the label. 406 * @param y 407 * The y coordinate of the label. 408 * @param g 409 * The graphics context. 410 */ 411 private void drawLabel(String s, int x, int y, Graphics g) { 412 drawLabel(s, x, y, g, Color.GRAY); 413 } 414 415 /** 416 * Draws a label within a filled rounded rectangle with the specified second gradient color (first color is <tt>Color.WHITE<tt>). 417 * 418 * @param s 419 * The text to draw. 420 * @param x 421 * The x coordinate of the label. 422 * @param y 423 * The y coordinate of the label. 424 * @param g 425 * The graphics context. 426 * @param secondGradColor 427 * The second color of the gradient. 428 */ 429 private void drawLabel(String s, int x, int y, Graphics g, 430 Color secondGradColor) { 431 Graphics2D g2d = (Graphics2D) g; 432 433 int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10; 434 int height = g.getFont().getSize() + g.getFontMetrics().getLeading() 435 + 5; 436 437 Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, 438 height); 439 440 if (isForbiddenArea(r)) { 441 return; // no space left, skip this label 442 } 443 444 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 445 RenderingHints.VALUE_ANTIALIAS_ON); 446 GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y 447 + (height / 2), secondGradColor, false); 448 g2d.setPaint(gradient); 449 450 g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 451 ROUND_RECT_RADIUS); 452 453 g2d.setColor(Color.BLACK); 454 455 g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 456 ROUND_RECT_RADIUS); 457 g2d.drawString(s, x - (width / 2) + 5, y + (height / 2) - 3); 458 459 forbiddenRects.add(r); 460 } 461 462 /** 463 * Draws a label with an additional triangle on the left side. 464 * 465 * @param s 466 * The text to draw. 467 * @param x 468 * The x coordinate of the label. 469 * @param y 470 * The y coordinate of the label. 471 * @param g 472 * The graphics context. 473 * @param secondGradColor 474 * The second color of the gradient. 475 * @param baseLength 476 * The base length of the triangle in pixels. 477 * @param triangleColor 478 * The color of the triangle. 479 * @param triangleDir 480 * The direction of the triangle. 481 */ 482 private void drawLabelWithTriangle(String s, int x, int y, Graphics g, 483 Color secondGradColor, int baseLength, Color triangleColor, 484 TriangleDir triangleDir) { 485 Graphics2D g2d = (Graphics2D) g; 486 487 int width = g.getFontMetrics(g.getFont()).stringWidth(s) + 10 + baseLength + 5; 488 int height = g.getFont().getSize() + g.getFontMetrics().getLeading() + 5; 489 490 Rectangle r = new Rectangle(x - (width / 2), y - (height / 2), width, height); 491 492 if (isForbiddenArea(r)) { 493 return; // no space left, skip this label 494 } 495 496 g2d.setRenderingHint(RenderingHints.KEY_ANTIALIASING, 497 RenderingHints.VALUE_ANTIALIAS_ON); 498 GradientPaint gradient = new GradientPaint(x, y, Color.WHITE, x, y 499 + (height / 2), secondGradColor, false); 500 g2d.setPaint(gradient); 501 502 g2d.fillRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 503 ROUND_RECT_RADIUS); 504 505 g2d.setColor(Color.BLACK); 506 507 g2d.drawRoundRect(r.x, r.y, r.width, r.height, ROUND_RECT_RADIUS, 508 ROUND_RECT_RADIUS); 509 g2d.drawString(s, x - (width / 2) + 8 + baseLength, y + (height / 2) - 3); 510 drawRegularTriangle(g2d, triangleColor, triangleDir, r.x + baseLength, 511 r.y + baseLength, baseLength); 512 513 forbiddenRects.add(r); 514 } 515 516 /** 517 * Checks, if the rectangle has been 'reserved' by an previous draw action. 518 * 519 * @param r 520 * The area to check for. 521 * @return true, if area is already occupied by another rectangle. 522 */ 523 private boolean isForbiddenArea(Rectangle r) { 524 525 for (Rectangle rTest : forbiddenRects) { 526 if (r.intersects(rTest)) 527 return true; 528 } 529 return false; 530 } 531 532 @Override 533 public void beginRendering() { 534 forbiddenRects.clear(); 535 } 536 537 @Override 538 public void finishRendering() { 539 // nothing to do currently 540 } 541 542 577 543 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationColors.java
r29921 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 20 7 21 8 /** 22 * Contains some extra predefined colors. 9 * Contains some extra predefined colors. 23 10 * @author Oliver Wieland <oliver.wieland@online.de> 24 11 */ 25 12 public class ElevationColors { 26 27 28 29 30 31 32 33 34 35 // TODO: Move to ColorMap.java or delete it 36 37 privateint ele; // limit38 privateColor color;39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 new ColorMapEntry(new Color(0,128, 0), 0), 58 new ColorMapEntry(new Color(156,187, 105), 1), 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 col = colors[1].getColor(); 81 82 83 84 col = colors[2].getColor(); 85 86 87 88 col = colors[3].getColor(); 89 90 91 92 col = Color.yellow; 93 94 95 96 col = Color.orange; 97 98 99 100 col = Color.lightGray; 101 102 103 104 col = Color.darkGray; 105 106 107 108 13 public static Color EPDarkBlue = new Color(21, 59, 99); 14 public static Color EPMidBlue = new Color(115, 140, 180); 15 public static Color EPLightBlue = new Color(176, 187, 208); 16 17 public static Color EPOrange = new Color(180, 140, 115); 18 19 public static Color EPLightBeige = new Color(235, 235, 215); 20 public static Color EPMidBeige = new Color(227, 222, 215); 21 22 // TODO: Move to ColorMap.java or delete it 23 static class ColorMapEntry { 24 private final int ele; // limit 25 private final Color color; 26 public ColorMapEntry(java.awt.Color color, int ele) { 27 super(); 28 this.color = color; 29 this.ele = ele; 30 } 31 32 public int getEle() { 33 return ele; 34 } 35 36 public Color getColor() { 37 return color; 38 } 39 } 40 41 42 43 private static ColorMapEntry[] colors = new ColorMapEntry[]{ 44 new ColorMapEntry(new Color(0,128, 0), 0), 45 new ColorMapEntry(new Color(156,187, 105), 1), 46 new ColorMapEntry(new Color(193,208, 107), 100), 47 new ColorMapEntry(new Color(244,224, 100), 200), 48 new ColorMapEntry(new Color(242,216, 149), 500), 49 new ColorMapEntry(new Color(234,191, 104), 1000), 50 new ColorMapEntry(new Color(207,169, 96), 2000), 51 }; 52 53 54 public static Color getElevationColor(double ele) { 55 if (!ElevationHelper.isValidElevation(ele)) { 56 return Color.white; 57 } 58 59 // TODO: Better color model... 60 Color col = Color.green; 61 62 if (ele < 0) { 63 col = Color.blue; 64 } 65 66 if (ele > 200) { 67 col = colors[1].getColor(); 68 } 69 70 if (ele > 300) { 71 col = colors[2].getColor(); 72 } 73 74 if (ele > 400) { 75 col = colors[3].getColor(); 76 } 77 78 if (ele > 500) { 79 col = Color.yellow; 80 } 81 82 if (ele > 750) { 83 col = Color.orange; 84 } 85 86 if (ele > 1000) { 87 col = Color.lightGray; 88 } 89 90 if (ele > 2000) { 91 col = Color.darkGray; 92 } 93 94 return col; 95 } 109 96 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java
r29982 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 52 39 import org.openstreetmap.josm.plugins.elevation.gpx.ElevationModel; 53 40 import org.openstreetmap.josm.tools.Shortcut; 41 54 42 /** 55 43 * @author Oliver Wieland <oliver.wieland@online.de> … … 93 81 */ 94 82 public ElevationProfileDialog() { 95 96 83 this(tr("Elevation Profile"), "elevation", 84 tr("Open the elevation profile window."), null, 200, true); 97 85 } 98 86 … … 101 89 */ 102 90 public ElevationProfileDialog(String name, String iconName, String tooltip, 103 104 91 Shortcut shortcut, int preferredHeight) { 92 this(name, iconName, tooltip, shortcut, preferredHeight, false); 105 93 } 106 94 … … 123 111 */ 124 112 public ElevationProfileDialog(String name, String iconName, String tooltip, 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 113 Shortcut shortcut, int preferredHeight, boolean defShow) { 114 super(name, iconName, tooltip, shortcut, preferredHeight, defShow); 115 116 // create model 117 model = new ElevationModel(); 118 119 // top panel 120 JPanel rootPanel = new JPanel(); 121 GridLayout gridLayout1 = new GridLayout(2, 1); 122 rootPanel.setLayout(gridLayout1); 123 124 // statistics panel 125 JPanel statPanel = new JPanel(); 126 GridLayout gridLayoutStat = new GridLayout(2, 6); 127 statPanel.setLayout(gridLayoutStat); 128 129 // first row: Headlines with bold font 130 String[] labels = new String[]{tr("Min"), tr("Avrg"), tr("Max"), tr("Dist"), tr("Gain"), tr("Time")}; 131 for (int i = 0; i < labels.length; i++) { 132 JLabel lbl = new JLabel(labels[i]); 133 lbl.setFont(getFont().deriveFont(Font.BOLD)); 134 statPanel.add(lbl); 135 } 136 137 // second row 138 minHeightLabel = new JLabel("0 m"); 139 statPanel.add(minHeightLabel); 140 avrgHeightLabel = new JLabel("0 m"); 141 statPanel.add(avrgHeightLabel); 142 maxHeightLabel = new JLabel("0 m"); 143 statPanel.add(maxHeightLabel); 144 distLabel = new JLabel("0 km"); 145 statPanel.add(distLabel); 146 elevationGainLabel = new JLabel("0 m"); 147 statPanel.add(elevationGainLabel); 148 totalTimeLabel = new JLabel("0"); 149 statPanel.add(totalTimeLabel); 150 151 // track selection panel 152 JPanel trackPanel = new JPanel(); 153 FlowLayout fl = new FlowLayout(FlowLayout.LEFT); 154 trackPanel.setLayout(fl); 155 156 JLabel lbTrack = new JLabel(tr("Tracks")); 157 lbTrack.setFont(getFont().deriveFont(Font.BOLD)); 158 trackPanel.add(lbTrack); 159 160 zoomButton = new JButton(tr("Zoom")); 161 zoomButton.addActionListener(new ActionListener() { 162 @Override 163 public void actionPerformed(ActionEvent arg0) { 164 if (model != null) { 165 IElevationProfile profile = model.getCurrentProfile(); 166 if (profile != null) { 167 Main.map.mapView.zoomTo(profile.getBounds()); 168 } 169 } 170 171 } 172 }); 173 zoomButton.setEnabled(false); 174 175 trackCombo = new JComboBox(new TrackModel()); 176 trackCombo.setPreferredSize(new Dimension(200, 24)); // HACK! 177 trackCombo.setEnabled(false); // we have no model on startup 178 179 trackPanel.add(trackCombo); 180 trackPanel.add(zoomButton); 181 182 // assemble root panel 183 rootPanel.add(statPanel); 184 rootPanel.add(trackPanel); 185 186 add(rootPanel, BorderLayout.PAGE_END); 187 188 // add chart component 189 profPanel = new ElevationProfilePanel(null); 190 add(profPanel, BorderLayout.CENTER); 191 profPanel.addComponentListener(this); 192 193 dock(); 206 194 } 207 195 208 196 @Override 209 197 public void showNotify() { 210 211 212 213 214 215 216 198 MapView.addLayerChangeListener(this); 199 if (Main.isDisplayingMapView()) { 200 Layer layer = Main.map.mapView.getActiveLayer(); 201 if (layer instanceof GpxLayer) { 202 setActiveLayer((GpxLayer) layer); 203 } 204 } 217 205 } 218 206 219 207 @Override 220 208 public void hideNotify() { 221 209 MapView.removeLayerChangeListener(this); 222 210 } 223 211 … … 227 215 */ 228 216 public IElevationModel getModel() { 229 217 return model; 230 218 } 231 219 … … 235 223 */ 236 224 public void setModel(IElevationModel model) { 237 238 239 240 241 225 if (this.model != model) { 226 this.model = model; 227 profPanel.setElevationModel(model); 228 updateView(); 229 } 242 230 } 243 231 … … 247 235 */ 248 236 public ElevationProfileLayer getProfileLayer() { 249 237 return profileLayer; 250 238 } 251 239 … … 255 243 */ 256 244 public void setProfileLayer(ElevationProfileLayer profileLayer) { 257 258 259 260 261 262 263 245 if (this.profileLayer != profileLayer) { 246 if (this.profileLayer != null) { 247 profPanel.removeSelectionListener(this.profileLayer); 248 } 249 this.profileLayer = profileLayer; 250 profPanel.addSelectionListener(this.profileLayer); 251 } 264 252 } 265 253 … … 270 258 @SuppressWarnings("unchecked") // TODO: Can be removed in Java 1.7 271 259 private void updateView() { 272 273 274 275 276 277 278 279 280 281 282 283 284 285 286 287 288 289 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 260 if (model == null) { 261 disableView(); 262 return; 263 } 264 265 IElevationProfile profile = model.getCurrentProfile(); 266 if (profile != null) { 267 // Show name of profile in title 268 setTitle(String.format("%s: %s", tr("Elevation Profile"), profile.getName())); 269 270 if (profile.hasElevationData()) { 271 // Show elevation data 272 minHeightLabel.setText( 273 ElevationHelper.getElevationText(profile.getMinHeight())); 274 maxHeightLabel.setText( 275 ElevationHelper.getElevationText(profile.getMaxHeight())); 276 avrgHeightLabel.setText( 277 ElevationHelper.getElevationText(profile.getAverageHeight())); 278 elevationGainLabel.setText( 279 ElevationHelper.getElevationText(profile.getGain())); 280 } 281 282 // compute values for time and distance 283 long diff = profile.getTimeDifference(); 284 long minutes = diff / (1000 * 60); 285 long hours = minutes / 60; 286 minutes = minutes % 60; 287 288 double dist = profile.getDistance(); 289 290 totalTimeLabel.setText(String.format("%d:%02d h", hours, minutes)); 291 distLabel.setText(NavigatableComponent.getSystemOfMeasurement().getDistText(dist)); 292 trackCombo.setEnabled(model.profileCount() > 1); 293 trackCombo.setModel(new TrackModel()); 294 zoomButton.setEnabled(true); 295 } else { // no elevation data, -> switch back to empty view 296 disableView(); 297 } 298 299 fireModelChanged(); 300 repaint(); 313 301 } 314 302 315 303 private void disableView() { 316 317 318 319 320 321 322 323 324 325 304 setTitle(String.format("%s: (No data)", tr("Elevation Profile"))); 305 306 minHeightLabel.setText(EMPTY_DATA_STRING); 307 maxHeightLabel.setText(EMPTY_DATA_STRING); 308 avrgHeightLabel.setText(EMPTY_DATA_STRING); 309 elevationGainLabel.setText(EMPTY_DATA_STRING); 310 totalTimeLabel.setText(EMPTY_DATA_STRING); 311 distLabel.setText(EMPTY_DATA_STRING); 312 trackCombo.setEnabled(false); 313 zoomButton.setEnabled(false); 326 314 } 327 315 … … 330 318 */ 331 319 protected void fireModelChanged() { 332 333 334 320 for (IElevationModelListener listener : listeners) { 321 listener.elevationProfileChanged(getModel().getCurrentProfile()); 322 } 335 323 } 336 324 … … 342 330 */ 343 331 public void addModelListener(IElevationModelListener listener) { 344 332 this.listeners.add(listener); 345 333 } 346 334 … … 352 340 */ 353 341 public void removeModelListener(IElevationModelListener listener) { 354 342 this.listeners.remove(listener); 355 343 } 356 344 … … 359 347 */ 360 348 public void removeAllListeners() { 361 this.listeners.clear(); 362 } 363 364 /* (non-Javadoc) 365 * @see org.openstreetmap.josm.gui.MapView.LayerChangeListener#activeLayerChange(org.openstreetmap.josm.gui.layer.Layer, org.openstreetmap.josm.gui.layer.Layer) 366 */ 349 this.listeners.clear(); 350 } 351 367 352 @Override 368 353 public void activeLayerChange(Layer oldLayer, Layer newLayer) { 369 370 371 354 if (newLayer instanceof GpxLayer) { 355 setActiveLayer((GpxLayer) newLayer); 356 } 372 357 } 373 358 374 359 private void setActiveLayer(GpxLayer newLayer) { 375 if (activeLayer != newLayer) { 376 activeLayer = newLayer; 377 378 // layer does not exist -> create 379 if (!layerMap.containsKey(newLayer)) { 380 GpxData gpxData = newLayer.data; 381 ElevationModel newEM = new ElevationModel(newLayer.getName(), 382 gpxData); 383 layerMap.put(newLayer, newEM); 384 } 385 386 ElevationModel em = layerMap.get(newLayer); 387 setModel(em); 388 } 389 } 390 391 /* (non-Javadoc) 392 * @see org.openstreetmap.josm.gui.MapView.LayerChangeListener#layerAdded(org.openstreetmap.josm.gui.layer.Layer) 393 */ 360 if (activeLayer != newLayer) { 361 activeLayer = newLayer; 362 363 // layer does not exist -> create 364 if (!layerMap.containsKey(newLayer)) { 365 GpxData gpxData = newLayer.data; 366 ElevationModel newEM = new ElevationModel(newLayer.getName(), 367 gpxData); 368 layerMap.put(newLayer, newEM); 369 } 370 371 ElevationModel em = layerMap.get(newLayer); 372 setModel(em); 373 } 374 } 375 394 376 @Override 395 377 public void layerAdded(Layer newLayer) { 396 if (newLayer instanceof GpxLayer) { 397 GpxLayer gpxLayer = (GpxLayer) newLayer; 398 setActiveLayer(gpxLayer); 399 } 400 } 401 402 /* (non-Javadoc) 403 * @see org.openstreetmap.josm.gui.MapView.LayerChangeListener#layerRemoved(org.openstreetmap.josm.gui.layer.Layer) 404 */ 378 if (newLayer instanceof GpxLayer) { 379 GpxLayer gpxLayer = (GpxLayer) newLayer; 380 setActiveLayer(gpxLayer); 381 } 382 } 383 405 384 @Override 406 385 public void layerRemoved(Layer oldLayer) { 407 if (layerMap.containsKey(oldLayer)) { 408 layerMap.remove(oldLayer); 409 } 410 411 if (layerMap.size() == 0) { 412 setModel(null); 413 if (profileLayer != null) { 414 profileLayer.setProfile(null); 415 } 416 } 417 } 418 419 /* 420 * (non-Javadoc) 421 * 422 * @seejava.awt.event.ComponentListener#componentHidden(java.awt.event. 423 * ComponentEvent) 424 */ 386 if (layerMap.containsKey(oldLayer)) { 387 layerMap.remove(oldLayer); 388 } 389 390 if (layerMap.size() == 0) { 391 setModel(null); 392 if (profileLayer != null) { 393 profileLayer.setProfile(null); 394 } 395 } 396 } 397 425 398 @Override 426 399 public void componentHidden(ComponentEvent e) { 427 400 } 428 401 429 /*430 * (non-Javadoc)431 *432 * @see433 * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent434 * )435 */436 402 @Override 437 403 public void componentMoved(ComponentEvent e) { 438 404 } 439 405 440 /*441 * (non-Javadoc)442 *443 * @seejava.awt.event.ComponentListener#componentResized(java.awt.event.444 * ComponentEvent)445 */446 406 @Override 447 407 public void componentResized(ComponentEvent e) { 448 408 } 449 409 450 /*451 * (non-Javadoc)452 *453 * @see454 * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent455 * )456 */457 410 @Override 458 411 public void componentShown(ComponentEvent e) { 459 412 } 460 461 413 462 414 @SuppressWarnings("rawtypes") // TODO: Can be removed in Java 1.7 463 415 class TrackModel implements ComboBoxModel { 464 465 466 467 468 469 470 471 472 473 474 475 476 477 478 479 480 481 482 483 484 485 486 487 488 489 490 491 492 493 494 495 496 497 498 499 500 501 502 503 504 505 506 507 508 509 510 511 416 private Collection<ListDataListener> listeners; 417 418 @Override 419 public void addListDataListener(ListDataListener arg0) { 420 if (listeners == null) { 421 listeners = new ArrayList<ListDataListener>(); 422 } 423 listeners.add(arg0); 424 } 425 426 @Override 427 public IElevationProfile getElementAt(int index) { 428 if (model == null) return null; 429 430 IElevationProfile ep = model.getProfiles().get(index); 431 return ep; 432 } 433 434 @Override 435 public int getSize() { 436 if (model == null) return 0; 437 438 return model.profileCount(); 439 } 440 441 @Override 442 public void removeListDataListener(ListDataListener listener) { 443 if (listeners == null) return; 444 445 listeners.remove(listener); 446 } 447 448 @Override 449 public Object getSelectedItem() { 450 if (model == null) return null; 451 452 return model.getCurrentProfile(); 453 } 454 455 @Override 456 public void setSelectedItem(Object selectedObject) { 457 if (model != null && selectedObject instanceof IElevationProfile) { 458 model.setCurrentProfile((IElevationProfile) selectedObject); 459 profileLayer.setProfile(model.getCurrentProfile()); 460 461 repaint(); 462 } 463 } 512 464 513 465 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileLayer.java
r29960 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 43 30 */ 44 31 public class ElevationProfileLayer extends Layer implements IElevationProfileSelectionListener { 45 32 46 33 private static final double Level_Factor = 100.0; 47 34 private IElevationProfile profile; 48 private IElevationProfileRenderer renderer = new DefaultElevationProfileRenderer();49 private WayPoint selWayPoint = null; 35 private final IElevationProfileRenderer renderer = new DefaultElevationProfileRenderer(); 36 private WayPoint selWayPoint = null; 50 37 51 38 /** … … 56 43 */ 57 44 public ElevationProfileLayer(String name) { 58 45 super(name); 59 46 } 60 47 … … 65 52 */ 66 53 public IElevationProfile getProfile() { 67 54 return profile; 68 55 } 69 56 … … 75 62 */ 76 63 public void setProfile(IElevationProfile profile) { 77 if (this.profile != profile) { 78 this.profile = profile; 79 Main.map.repaint(); 80 } 81 } 82 83 /* 84 * (non-Javadoc) 85 * 86 * @see org.openstreetmap.josm.gui.layer.Layer#getIcon() 87 */ 64 if (this.profile != profile) { 65 this.profile = profile; 66 Main.map.repaint(); 67 } 68 } 69 88 70 @Override 89 71 public Icon getIcon() { 90 return ImageProvider.get("layer", "elevation"); 91 } 92 93 /* 94 * (non-Javadoc) 95 * 96 * @see org.openstreetmap.josm.gui.layer.Layer#getInfoComponent() 97 */ 72 return ImageProvider.get("layer", "elevation"); 73 } 74 98 75 @Override 99 76 public Object getInfoComponent() { 100 return getToolTipText(); 101 } 102 103 /* 104 * (non-Javadoc) 105 * 106 * @see org.openstreetmap.josm.gui.layer.Layer#getMenuEntries() 107 */ 77 return getToolTipText(); 78 } 79 108 80 @Override 109 81 public Action[] getMenuEntries() { 110 // TODO: More entries??? 111 return new Action[] { new LayerListPopup.InfoAction(this) }; 112 } 113 114 /* 115 * (non-Javadoc) 116 * 117 * @see org.openstreetmap.josm.gui.layer.Layer#getToolTipText() 118 */ 82 // TODO: More entries??? 83 return new Action[] { new LayerListPopup.InfoAction(this) }; 84 } 85 119 86 @Override 120 87 public String getToolTipText() { 121 if (profile != null) { 122 return tr("Elevation profile for track ''{0}''.", profile.getName()); 123 } else { 124 return tr("Elevation profile"); 125 } 126 } 127 128 /* 129 * (non-Javadoc) 130 * 131 * @see 132 * org.openstreetmap.josm.gui.layer.Layer#isMergable(org.openstreetmap.josm 133 * .gui.layer.Layer) 134 */ 88 if (profile != null) { 89 return tr("Elevation profile for track ''{0}''.", profile.getName()); 90 } else { 91 return tr("Elevation profile"); 92 } 93 } 94 135 95 @Override 136 96 public boolean isMergable(Layer other) { 137 return false; 138 } 139 140 /* 141 * (non-Javadoc) 142 * 143 * @see 144 * org.openstreetmap.josm.gui.layer.Layer#mergeFrom(org.openstreetmap.josm 145 * .gui.layer.Layer) 146 */ 97 return false; 98 } 99 147 100 @Override 148 101 public void mergeFrom(Layer from) { 149 // nothing to do 150 } 151 152 /* 153 * (non-Javadoc) 154 * 155 * @see org.openstreetmap.josm.gui.layer.Layer#paint(java.awt.Graphics2D, 156 * org.openstreetmap.josm.gui.MapView, org.openstreetmap.josm.data.Bounds) 157 */ 102 // nothing to do 103 } 104 158 105 @Override 159 106 public void paint(Graphics2D g, MapView mv, Bounds box) { 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 185 186 // now we paint special way points in emphasized style 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 } 208 209 107 WayPoint lastWpt = null; 108 109 renderer.beginRendering(); 110 111 if (profile != null) { 112 // choose smaller font 113 Font oldFont = g.getFont(); 114 Font lFont = g.getFont().deriveFont(9.0f); 115 g.setFont(lFont); 116 117 try { 118 // paint way points one by one 119 for (WayPoint wpt : profile.getWayPoints()) { 120 if (lastWpt != null) { 121 // determine way point 122 ElevationWayPointKind kind = classifyWayPoint(lastWpt, wpt); 123 // render way point as line 124 renderer.renderLine(g, profile, mv, lastWpt, wpt, kind); 125 // render single way point 126 renderer.renderWayPoint(g, profile, mv, wpt, kind); 127 } // else first way point -> is paint later 128 129 // remember last wpt for next iteration 130 lastWpt = wpt; 131 } 132 133 // now we paint special way points in emphasized style 134 135 // paint start/end 136 renderer.renderWayPoint(g, profile, mv, profile.getStartWayPoint(), 137 ElevationWayPointKind.StartPoint); 138 renderer.renderWayPoint(g, profile, mv, profile.getEndWayPoint(), 139 ElevationWayPointKind.EndPoint); 140 // paint min/max 141 renderer.renderWayPoint(g, profile, mv, profile.getMaxWayPoint(), 142 ElevationWayPointKind.MaxElevation); 143 renderer.renderWayPoint(g, profile, mv, profile.getMinWayPoint(), 144 ElevationWayPointKind.MinElevation); 145 146 147 // paint selected way point, if available 148 if (selWayPoint != null) { 149 renderer.renderWayPoint(g, profile, mv, selWayPoint, 150 ElevationWayPointKind.Highlighted); 151 } 152 } finally { 153 g.setFont(oldFont); 154 } 155 } 156 renderer.finishRendering(); 210 157 } 211 158 … … 217 164 * 218 165 * @param lastWpt the last way point 219 * @param actWpt the actual way point 166 * @param actWpt the actual way point 220 167 * @return the elevation way point kind 221 168 */ 222 169 private ElevationWayPointKind classifyWayPoint(WayPoint lastWpt, WayPoint actWpt) { 223 // get elevation values 224 int actEle = (int) ElevationHelper.getElevation(actWpt); 225 int lastEle = (int) ElevationHelper.getElevation(lastWpt); 226 227 // normalize elevation to levels 228 int actLevel = (int)(actEle / Level_Factor); 229 int lastLevel = (int)(lastEle / Level_Factor); 230 double slope = Math.abs(ElevationHelper.computeSlope(lastWpt.getCoor(), actWpt.getCoor())); 231 232 // plain way point by default 233 ElevationWayPointKind kind = ElevationWayPointKind.Plain; 234 235 // check, if we passed an elevation level 236 // We assume, that we cannot pass more than one levels between two way points ;-) 237 if (actLevel != lastLevel && Math.abs(actLevel - lastLevel) == 1) { 238 if (actLevel > lastLevel) { // we went down? 239 kind =ElevationWayPointKind.ElevationLevelGain; 240 } else { 241 kind =ElevationWayPointKind.ElevationLevelLoss; 242 } 243 } else { // check for elevation gain or loss 244 if (actEle > lastEle) { // we went uphill? 245 // TODO: Provide parameters for high/low thresholds 246 if (slope > 2) kind =ElevationWayPointKind.ElevationGainLow; 247 if (slope > 15) kind =ElevationWayPointKind.ElevationGainHigh; 248 } else { 249 if (slope > 2) kind =ElevationWayPointKind.ElevationLossLow; 250 if (slope > 15) kind =ElevationWayPointKind.ElevationLossHigh; 251 } 252 } 253 return kind; 254 } 255 256 /* 257 * (non-Javadoc) 258 * 259 * @see 260 * org.openstreetmap.josm.gui.layer.Layer#visitBoundingBox(org.openstreetmap 261 * .josm.data.osm.visitor.BoundingXYVisitor) 262 */ 170 // get elevation values 171 int actEle = (int) ElevationHelper.getElevation(actWpt); 172 int lastEle = (int) ElevationHelper.getElevation(lastWpt); 173 174 // normalize elevation to levels 175 int actLevel = (int)(actEle / Level_Factor); 176 int lastLevel = (int)(lastEle / Level_Factor); 177 double slope = Math.abs(ElevationHelper.computeSlope(lastWpt.getCoor(), actWpt.getCoor())); 178 179 // plain way point by default 180 ElevationWayPointKind kind = ElevationWayPointKind.Plain; 181 182 // check, if we passed an elevation level 183 // We assume, that we cannot pass more than one levels between two way points ;-) 184 if (actLevel != lastLevel && Math.abs(actLevel - lastLevel) == 1) { 185 if (actLevel > lastLevel) { // we went down? 186 kind =ElevationWayPointKind.ElevationLevelGain; 187 } else { 188 kind =ElevationWayPointKind.ElevationLevelLoss; 189 } 190 } else { // check for elevation gain or loss 191 if (actEle > lastEle) { // we went uphill? 192 // TODO: Provide parameters for high/low thresholds 193 if (slope > 2) kind =ElevationWayPointKind.ElevationGainLow; 194 if (slope > 15) kind =ElevationWayPointKind.ElevationGainHigh; 195 } else { 196 if (slope > 2) kind =ElevationWayPointKind.ElevationLossLow; 197 if (slope > 15) kind =ElevationWayPointKind.ElevationLossHigh; 198 } 199 } 200 return kind; 201 } 202 263 203 @Override 264 204 public void visitBoundingBox(BoundingXYVisitor v) { 265 // What to do here? 205 // What to do here? 266 206 } 267 207 268 208 @Override 269 209 public void selectedWayPointChanged(WayPoint newWayPoint) { 270 271 272 273 210 if (selWayPoint != newWayPoint) { 211 selWayPoint = newWayPoint; 212 Main.map.repaint(); 213 } 274 214 } 275 215 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java
r29982 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation.gui; 15 3 … … 67 55 */ 68 56 public ElevationProfilePanel(IElevationModel profile) { 69 70 71 72 73 74 75 76 77 78 57 super(); 58 this.model = profile; 59 setDoubleBuffered(true); 60 setBackground(Color.WHITE); 61 createOrUpdatePlotArea(); 62 addComponentListener(this); 63 addMouseMotionListener(this); 64 65 Font lFont = getFont().deriveFont(9.0f); 66 setFont(lFont); 79 67 } 80 68 … … 84 72 */ 85 73 public IElevationModel getProfile() { 86 74 return model; 87 75 } 88 76 … … 92 80 */ 93 81 public void setElevationModel(IElevationModel model) { 94 95 96 97 82 if (this.model != model) { 83 this.model = model; 84 invalidate(); 85 } 98 86 } 99 87 … … 103 91 */ 104 92 public Rectangle getPlotArea() { 105 93 return plotArea; 106 94 } 107 95 … … 111 99 */ 112 100 public void setPlotArea(Rectangle plotArea) { 113 101 this.plotArea = plotArea; 114 102 } 115 103 … … 119 107 */ 120 108 public int getSelectedIndex() { 121 109 return selectedIndex; 122 110 } 123 111 … … 127 115 */ 128 116 public void setSelectedIndex(int selectedIndex) { 129 130 131 132 133 117 this.selectedIndex = selectedIndex; 118 119 if (model != null) { 120 model.setCurrentProfile(selectedIndex); 121 } 134 122 } 135 123 … … 139 127 */ 140 128 public WayPoint getSelectedWayPoint() { 141 142 143 144 145 146 147 148 149 150 129 if (model == null) return null; 130 131 IElevationProfile profile = model.getCurrentProfile(); 132 133 int selWp = this.selectedIndex * step; 134 if (profile != null && profile.getWayPoints() != null && selWp > 0 && profile.getWayPoints().size() > selWp) { 135 return profile.getWayPoints().get(selWp); 136 } else { 137 return null; 138 } 151 139 } 152 140 … … 156 144 */ 157 145 public void addSelectionListener(IElevationProfileSelectionListener listener) { 158 159 160 146 if (listener == null) return; 147 148 selectionChangedListeners.add(listener); 161 149 } 162 150 … … 166 154 */ 167 155 public void removeSelectionListener(IElevationProfileSelectionListener listener) { 168 169 170 156 if (listener == null) return; 157 158 selectionChangedListeners.remove(listener); 171 159 } 172 160 … … 175 163 */ 176 164 public void removeAllSelectionListeners() { 177 165 selectionChangedListeners.clear(); 178 166 } 179 167 180 168 protected void fireSelectionChanged(WayPoint selWayPoint) { 181 for (IElevationProfileSelectionListener listener : selectionChangedListeners) { 182 listener.selectedWayPointChanged(selWayPoint); 183 } 184 } 185 186 /* (non-Javadoc) 187 * @see javax.swing.JComponent#paint(java.awt.Graphics) 188 */ 169 for (IElevationProfileSelectionListener listener : selectionChangedListeners) { 170 listener.selectedWayPointChanged(selWayPoint); 171 } 172 } 173 189 174 @Override 190 175 public void paint(Graphics g) { 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 206 207 208 209 210 211 212 213 214 215 216 217 218 219 220 221 222 223 224 225 226 227 228 229 176 isPainting = true; 177 178 try { 179 super.paint(g); 180 createOrUpdatePlotArea(); 181 int y1 = getPlotBottom(); 182 183 g.setColor(Color.DARK_GRAY); 184 g.drawLine(plotArea.x, plotArea.y, plotArea.x, plotArea.y 185 + plotArea.height); 186 g.drawLine(plotArea.x, plotArea.y + plotArea.height, plotArea.x 187 + plotArea.width, plotArea.y + plotArea.height); 188 189 190 if (model != null) { 191 IElevationProfile profile = model.getCurrentProfile(); 192 if (profile != null && profile.hasElevationData()) { 193 // Draw start and end date 194 drawAlignedString(formatDate(profile.getStart()), 5, y1 + BOTTOM_TEXT_Y_OFFSET, 195 TextAlignment.Left, g); 196 drawAlignedString(formatDate(profile.getEnd()), 197 getPlotRight(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Right, g); 198 199 // Show SRTM indicator 200 if (ElevationHelper.hasSrtmData(profile.getBounds())) { 201 String txt = "SRTM"; 202 drawAlignedString(txt, getPlotHCenter(), y1 + BOTTOM_TEXT_Y_OFFSET, TextAlignment.Centered, g); 203 } 204 drawProfile(g); 205 drawElevationLines(g); 206 } else { 207 // No profile or profile supports no elevation data 208 drawAlignedString(tr("(No elevation data)"), getPlotHCenter(), 209 getPlotVCenter(), TextAlignment.Centered, g); 210 } 211 } 212 } finally { 213 isPainting = false; 214 } 230 215 } 231 216 … … 240 225 */ 241 226 private Rectangle drawAlignedString(String s, int x, int y, 242 243 244 245 246 247 248 249 250 251 252 253 254 255 256 257 258 259 227 TextAlignment align, Graphics g) { 228 FontMetrics fm = g.getFontMetrics(); 229 int w = fm.stringWidth(s); 230 int h = fm.getHeight(); 231 232 int xoff = w / 2; 233 int yoff = h / 2; 234 235 if (align == TextAlignment.Left) { 236 xoff = 0; 237 } 238 if (align == TextAlignment.Right) { 239 xoff = w; 240 } 241 242 g.drawString(s, x - xoff, y + yoff); 243 244 return new Rectangle(x - xoff, y - yoff, w, h); 260 245 } 261 246 … … 268 253 * @return The resulting rectangle of the drawn string. 269 254 270 271 272 255 private void drawHCenteredString(String s, int x, int y, Graphics g) { 256 drawAlignedString(s, x, y, TextAlignment.Centered, g); 257 }*/ 273 258 274 259 /** … … 278 263 */ 279 264 private String formatDate(Date date) { 280 281 282 265 Format formatter = new SimpleDateFormat("d MMM yy, HH:mm"); 266 267 return formatter.format(date); 283 268 } 284 269 … … 288 273 */ 289 274 private void drawElevationLines(Graphics g) { 290 291 292 293 294 295 296 297 298 299 300 301 302 303 304 305 306 307 308 309 310 311 312 313 314 315 316 317 318 319 320 321 322 323 324 325 326 327 328 329 330 331 332 275 IElevationProfile profile = model.getCurrentProfile(); 276 277 double diff = profile.getHeightDifference(); 278 279 if (diff == 0.0) { 280 return; 281 } 282 283 double z10 = Math.floor(Math.log10(diff)); 284 double scaleUnit = Math.pow(10, z10); // scale unit, e. g. 100 for 285 // values below 1000 286 287 int upperLimit = (int) (Math.round(Math.ceil(profile.getMaxHeight() 288 / scaleUnit)) * scaleUnit); 289 int lowerLimit = (int) (Math.round(Math.floor(profile.getMinHeight() 290 / scaleUnit)) * scaleUnit); 291 int su = (int) scaleUnit; 292 293 for (int i = lowerLimit; i <= upperLimit; i += su) { 294 int yLine = getYForEelevation(i); 295 296 // check bounds 297 if (yLine <= getPlotBottom() && yLine >= getPlotTop()) { 298 String txt = ElevationHelper.getElevationText(i); 299 300 Rectangle r = drawAlignedString(txt, getPlotHCenter(), yLine - 2, 301 TextAlignment.Right, g); 302 r.grow(2, 2); 303 304 // Draw left and right line segment 305 g.drawLine(getPlotLeftAxis(), yLine, r.x, 306 yLine); 307 g.drawLine(r.x + r.width, yLine, getPlotRight(), 308 yLine); 309 // Draw label with shadow 310 g.setColor(Color.WHITE); 311 drawAlignedString(txt, getPlotHCenter() + 1, yLine - 1, 312 TextAlignment.Right, g); 313 g.setColor(Color.BLACK); 314 drawAlignedString(txt, getPlotHCenter(), yLine - 2, 315 TextAlignment.Right, g); 316 } 317 } 333 318 } 334 319 … … 340 325 */ 341 326 private int getPlotLeftAxis() { 342 327 return plotArea.x - 3; 343 328 } 344 329 … … 349 334 */ 350 335 private int getPlotLeft() { 351 336 return plotArea.x + 1; 352 337 } 353 338 … … 358 343 */ 359 344 private int getPlotHCenter() { 360 345 return (getPlotLeft() + getPlotRight()) / 2; 361 346 } 362 347 … … 367 352 */ 368 353 private int getPlotVCenter() { 369 354 return (getPlotTop() + getPlotBottom()) / 2; 370 355 } 371 356 … … 376 361 */ 377 362 private int getPlotRight() { 378 363 return plotArea.x + plotArea.width - 1; 379 364 } 380 365 381 366 private int getPlotBottom() { 382 367 return plotArea.y + plotArea.height - 1; 383 368 } 384 369 385 370 private int getPlotTop() { 386 371 return plotArea.y + 1; 387 372 } 388 373 … … 394 379 */ 395 380 private int getYForEelevation(int elevation) { 396 397 398 399 400 401 402 403 404 405 406 381 int y1 = getPlotBottom(); 382 383 IElevationProfile profile = model.getCurrentProfile(); 384 385 if (!profile.hasElevationData()) { 386 return y1; 387 } 388 389 double diff = profile.getHeightDifference(); 390 391 return y1 - (int) Math.round(((elevation - profile.getMinHeight()) / diff * plotArea.height)); 407 392 } 408 393 … … 413 398 */ 414 399 private void drawProfile(Graphics g) { 415 IElevationProfile profile = model.getCurrentProfile(); 416 417 int nwp = profile.getNumberOfWayPoints(); 418 int n = Math.min(plotArea.width, nwp); 419 420 if (n == 0) return; // nothing to draw 421 // compute step size in panel (add 1 to make sure that 422 // the complete range fits into panel 423 step = (nwp / n) + 1; 424 425 int yBottom = getPlotBottom(); 426 Color oldC = g.getColor(); 427 428 for (int i = 0, ip = 0; i < n && ip < nwp; i++, ip += step) { 429 WayPoint wpt = profile.getWayPoints().get(ip); 430 int eleVal = (int) ElevationHelper.getElevation(wpt); 431 Color c = renderer.getColorForWaypoint(profile, wpt, 432 ElevationWayPointKind.Plain); 433 434 // draw cursor 435 if (i == this.selectedIndex) { 436 g.setColor(Color.BLACK); 437 drawAlignedString(ElevationHelper.getElevationText(eleVal), 438 (getPlotRight() + getPlotLeft()) / 2, 439 getPlotBottom() + 6, 440 TextAlignment.Centered, 441 g); 442 443 c = renderer.getColorForWaypoint(profile, wpt, ElevationWayPointKind.Highlighted); 444 } 445 446 int yEle = getYForEelevation(eleVal); 447 int x = getPlotLeft() + i; 448 449 g.setColor(c); 450 g.drawLine(x, yBottom, x, yEle); 451 g.setColor(ElevationColors.EPLightBlue); 452 } 453 454 g.setColor(oldC); 455 } 456 457 458 /* (non-Javadoc) 459 * @see javax.swing.JComponent#paintBorder(java.awt.Graphics) 460 */ 400 IElevationProfile profile = model.getCurrentProfile(); 401 402 int nwp = profile.getNumberOfWayPoints(); 403 int n = Math.min(plotArea.width, nwp); 404 405 if (n == 0) return; // nothing to draw 406 // compute step size in panel (add 1 to make sure that 407 // the complete range fits into panel 408 step = (nwp / n) + 1; 409 410 int yBottom = getPlotBottom(); 411 Color oldC = g.getColor(); 412 413 for (int i = 0, ip = 0; i < n && ip < nwp; i++, ip += step) { 414 WayPoint wpt = profile.getWayPoints().get(ip); 415 int eleVal = (int) ElevationHelper.getElevation(wpt); 416 Color c = renderer.getColorForWaypoint(profile, wpt, 417 ElevationWayPointKind.Plain); 418 419 // draw cursor 420 if (i == this.selectedIndex) { 421 g.setColor(Color.BLACK); 422 drawAlignedString(ElevationHelper.getElevationText(eleVal), 423 (getPlotRight() + getPlotLeft()) / 2, 424 getPlotBottom() + 6, 425 TextAlignment.Centered, 426 g); 427 428 c = renderer.getColorForWaypoint(profile, wpt, ElevationWayPointKind.Highlighted); 429 } 430 431 int yEle = getYForEelevation(eleVal); 432 int x = getPlotLeft() + i; 433 434 g.setColor(c); 435 g.drawLine(x, yBottom, x, yEle); 436 g.setColor(ElevationColors.EPLightBlue); 437 } 438 439 g.setColor(oldC); 440 } 441 461 442 @Override 462 443 protected void paintBorder(Graphics g) { 463 super.paintBorder(g); 464 465 Border loweredbevel = BorderFactory.createLoweredBevelBorder(); 466 this.setBorder(loweredbevel); 467 } 468 444 super.paintBorder(g); 445 446 Border loweredbevel = BorderFactory.createLoweredBevelBorder(); 447 this.setBorder(loweredbevel); 448 } 469 449 470 450 /** … … 472 452 */ 473 453 private void createOrUpdatePlotArea() { 474 Dimension caSize = getSize(); 475 476 if (plotArea == null) { 477 plotArea = new Rectangle(0, 0, caSize.width, caSize.height); 478 } else { 479 plotArea.width = caSize.width; 480 plotArea.height = caSize.height; 481 } 482 483 plotArea.setLocation(0, 0); 484 plotArea.grow(-10, -15); 485 } 486 487 /* 488 * (non-Javadoc) 489 * 490 * @seejava.awt.event.ComponentListener#componentHidden(java.awt.event. 491 * ComponentEvent) 492 */ 454 Dimension caSize = getSize(); 455 456 if (plotArea == null) { 457 plotArea = new Rectangle(0, 0, caSize.width, caSize.height); 458 } else { 459 plotArea.width = caSize.width; 460 plotArea.height = caSize.height; 461 } 462 463 plotArea.setLocation(0, 0); 464 plotArea.grow(-10, -15); 465 } 466 493 467 @Override 494 468 public void componentHidden(ComponentEvent arg0) { 495 // TODO Auto-generated method stub 496 } 497 498 /* 499 * (non-Javadoc) 500 * 501 * @see 502 * java.awt.event.ComponentListener#componentMoved(java.awt.event.ComponentEvent 503 * ) 504 */ 469 // TODO Auto-generated method stub 470 } 471 505 472 @Override 506 473 public void componentMoved(ComponentEvent arg0) { 507 // TODO Auto-generated method stub 508 } 509 510 /* 511 * (non-Javadoc) 512 * 513 * @seejava.awt.event.ComponentListener#componentResized(java.awt.event. 514 * ComponentEvent) 515 */ 474 // TODO Auto-generated method stub 475 } 476 516 477 @Override 517 478 public void componentResized(ComponentEvent arg0) { 518 createOrUpdatePlotArea(); 519 } 520 521 /* 522 * (non-Javadoc) 523 * 524 * @see 525 * java.awt.event.ComponentListener#componentShown(java.awt.event.ComponentEvent 526 * ) 527 */ 479 createOrUpdatePlotArea(); 480 } 481 528 482 @Override 529 483 public void componentShown(ComponentEvent arg0) { 530 // TODO Auto-generated method stub 531 484 // TODO Auto-generated method stub 532 485 } 533 486 534 487 @Override 535 488 public void mouseDragged(MouseEvent arg0) { 536 489 // TODO Auto-generated method stub 537 490 538 491 } … … 540 493 @Override 541 494 public void mouseMoved(MouseEvent arg0) { 542 543 544 545 546 547 548 549 550 551 552 553 495 if (isPainting || arg0.isControlDown() || arg0.isAltDown() || arg0.isShiftDown()) arg0.consume(); 496 497 int x = arg0.getX(); 498 int l = this.getX(); 499 int pl = this.getPlotLeft(); 500 int newIdx = x - l - pl; 501 502 if (newIdx != this.selectedIndex && newIdx >= 0) { 503 this.selectedIndex = newIdx; 504 this.repaint(); 505 fireSelectionChanged(getSelectedWayPoint()); 506 } 554 507 } 555 508 556 509 @Override 557 510 public String getToolTipText() { 558 559 560 561 562 563 511 WayPoint wpt = getSelectedWayPoint(); 512 if (wpt != null) { 513 return String.format("%s: %s", ElevationHelper.getTimeText(wpt), ElevationHelper.getElevationText(wpt)); 514 } 515 516 return super.getToolTipText(); 564 517 } 565 518 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/IElevationProfileRenderer.java
r29955 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 27 14 * for a given way point, so that as well the dialog as the layer can share the color scheme. 28 15 * Second, the layer can simply pass the painting stuff to a renderer without taking care of 29 * details. 16 * details. 30 17 * 31 18 * @author Oliver Wieland <oliver.wieland@online.de> … … 33 20 */ 34 21 public interface IElevationProfileRenderer { 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 22 /** 23 * Gets the color for a given way point. 24 * @param profile The elevation profile that contains the way point. 25 * @param wpt The way point to get the color for. 26 * @param kind The way point kind (see {@link ElevationWayPointKind}). 27 * @return The color for the way point or null, if invalid arguments have been specified. 28 */ 29 Color getColorForWaypoint(IElevationProfile profile, WayPoint wpt, ElevationWayPointKind kind); 30 31 /** 32 * Renders the way point with the lowest elevation. 33 * 34 * @param g The graphics context. 35 * @param profile The elevation profile that contains the way point. 36 * @param mv the associated view 37 * @param wpt The way point to render. 38 * @param kind The way point kind (see {@link ElevationWayPointKind}). 39 */ 40 void renderWayPoint(Graphics g, IElevationProfile profile, MapView mv, WayPoint wpt, ElevationWayPointKind kind); 41 42 /** 43 * Render line between two way points. This is intended to render speed or slope. 44 * 45 * @param g The graphics context. 46 * @param profile The elevation profile that contains the way point. 47 * @param mv the associated view 48 * @param wpt1 the first way point 49 * @param wpt2 the second way point 50 */ 51 void renderLine(Graphics g, IElevationProfile profile, MapView mv, WayPoint wpt1, WayPoint wpt2, ElevationWayPointKind kind); 52 53 /** 54 * Notifies the renderer that rendering starts. 55 */ 56 void beginRendering(); 57 58 /** 59 * Notifies the renderer that rendering has been finished. 60 */ 61 void finishRendering(); 75 62 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/IElevationProfileSelectionListener.java
r23795 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 1 // License: GPL. For details, see LICENSE file. 14 2 package org.openstreetmap.josm.plugins.elevation.gui; 15 3 … … 17 5 18 6 public interface IElevationProfileSelectionListener { 19 20 * Notifies clients about selected index changed. 21 22 23 7 /** 8 * Notifies clients about selected index changed. 9 * @param newIndex 10 */ 11 public void selectedWayPointChanged(WayPoint wpt); 24 12 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/TextAlignment.java
r23795 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 20 7 */ 21 8 public enum TextAlignment { 22 23 24 9 Left, 10 Right, 11 Centered 25 12 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/Triangle.java
r23795 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 30 17 */ 31 18 public class Triangle implements Shape { 32 privatePolygon poly;19 private final Polygon poly; 33 20 34 35 36 37 38 39 40 41 21 /** 22 * Copy constructor. 23 * @param p 24 */ 25 public Triangle(Polygon p) { 26 if (p == null || p.npoints != 3) throw new RuntimeException("Given polygon was null or had invalid number of points"); 27 poly = p; 28 } 42 29 43 44 45 46 47 48 49 50 51 52 53 54 poly.addPoint(p3.x, p3.y); 55 30 /** 31 * Creates a triangle from 3 given points. The points are used without any sanity check, so it is up to 32 * the user that the points form a triangle. 33 * @param p1 34 * @param p2 35 * @param p3 36 */ 37 public Triangle(Point p1, Point p2, Point p3) { 38 poly = new Polygon(); 39 poly.addPoint(p1.x, p1.y); 40 poly.addPoint(p2.x, p2.y); 41 poly.addPoint(p3.x, p3.y); 42 } 56 43 57 58 59 60 61 62 63 44 /** 45 * Draws an outlined triangle. 46 * @param g 47 */ 48 public void draw(Graphics g) { 49 g.drawPolygon(poly); 50 } 64 51 65 66 67 68 69 70 71 52 /** 53 * Draws a filled triangle. 54 * @param g 55 */ 56 public void fill(Graphics g) { 57 g.fillPolygon(poly); 58 } 72 59 73 /* (non-Javadoc) 74 * @see java.awt.Shape#getBounds() 75 */ 76 public Rectangle getBounds() { 77 return poly.getBounds(); 78 } 60 @Override 61 public Rectangle getBounds() { 62 return poly.getBounds(); 63 } 79 64 80 /* (non-Javadoc) 81 * @see java.awt.Shape#getBounds2D() 82 */ 83 public Rectangle2D getBounds2D() { 84 return poly.getBounds2D(); 85 } 65 @Override 66 public Rectangle2D getBounds2D() { 67 return poly.getBounds2D(); 68 } 86 69 87 /* (non-Javadoc) 88 * @see java.awt.Shape#contains(double, double) 89 */ 90 public boolean contains(double x, double y) { 91 return poly.contains(x, y); 92 } 70 @Override 71 public boolean contains(double x, double y) { 72 return poly.contains(x, y); 73 } 93 74 94 /* (non-Javadoc) 95 * @see java.awt.Shape#contains(java.awt.geom.Point2D) 96 */ 97 public boolean contains(Point2D p) { 98 return poly.contains(p); 99 } 75 @Override 76 public boolean contains(Point2D p) { 77 return poly.contains(p); 78 } 100 79 101 /* (non-Javadoc) 102 * @see java.awt.Shape#intersects(double, double, double, double) 103 */ 104 public boolean intersects(double x, double y, double w, double h) { 105 return poly.intersects(x, y, w, h); 106 } 80 @Override 81 public boolean intersects(double x, double y, double w, double h) { 82 return poly.intersects(x, y, w, h); 83 } 107 84 108 /* (non-Javadoc) 109 * @see java.awt.Shape#intersects(java.awt.geom.Rectangle2D) 110 */ 111 public boolean intersects(Rectangle2D r) { 112 return poly.intersects(r); 113 } 85 @Override 86 public boolean intersects(Rectangle2D r) { 87 return poly.intersects(r); 88 } 114 89 115 /* (non-Javadoc) 116 * @see java.awt.Shape#contains(double, double, double, double) 117 */ 118 public boolean contains(double x, double y, double w, double h) { 119 return poly.contains(x, y, w, h); 120 } 90 @Override 91 public boolean contains(double x, double y, double w, double h) { 92 return poly.contains(x, y, w, h); 93 } 121 94 122 /* (non-Javadoc) 123 * @see java.awt.Shape#contains(java.awt.geom.Rectangle2D) 124 */ 125 public boolean contains(Rectangle2D r) { 126 return poly.intersects(r); 127 } 95 @Override 96 public boolean contains(Rectangle2D r) { 97 return poly.intersects(r); 98 } 128 99 129 /* (non-Javadoc) 130 * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform) 131 */ 132 public PathIterator getPathIterator(AffineTransform at) { 133 return poly.getPathIterator(at); 134 } 100 @Override 101 public PathIterator getPathIterator(AffineTransform at) { 102 return poly.getPathIterator(at); 103 } 135 104 136 /* (non-Javadoc) 137 * @see java.awt.Shape#getPathIterator(java.awt.geom.AffineTransform, double) 138 */ 139 public PathIterator getPathIterator(AffineTransform at, double flatness) { 140 return poly.getPathIterator(at, flatness); 141 } 142 105 @Override 106 public PathIterator getPathIterator(AffineTransform at, double flatness) { 107 return poly.getPathIterator(at, flatness); 108 } 143 109 } -
applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/TriangleDir.java
r23795 r30344 1 /** 2 * This program is free software: you can redistribute it and/or modify it under 3 * the terms of the GNU General Public License as published by the 4 * Free Software Foundation, either version 3 of the License, or 5 * (at your option) any later version. 6 * 7 * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 8 * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 9 * See the GNU General Public License for more details. 10 * 11 * You should have received a copy of the GNU General Public License along with this program. 12 * If not, see <http://www.gnu.org/licenses/>. 13 */ 14 1 // License: GPL. For details, see LICENSE file. 15 2 package org.openstreetmap.josm.plugins.elevation.gui; 16 3 … … 20 7 */ 21 8 public enum TriangleDir { 22 23 24 25 9 Up, 10 Down, 11 Left, 12 Right 26 13 } -
applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/EleVertexTest.java
r29964 r30344 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.plugins.elevation.tests; 2 3 … … 18 19 * Setup test. 19 20 */ 21 @Override 20 22 public void setUp() { 21 23 Main.pref = new Preferences(); 22 24 } 23 25 24 26 public void testDivide() { 25 26 27 28 29 30 31 32 33 34 // 1st vertex (p1, p2, pN 105m) 35 36 37 38 39 40 41 // 2nd vertex (p3, p2, pN = 105m) 42 43 44 45 46 47 27 EleCoordinate p1 = new EleCoordinate(30.0, 30.0, 100.0); 28 EleCoordinate p2 = new EleCoordinate(35.0, 30.0, 120.0); 29 EleCoordinate p3 = new EleCoordinate(35.0, 40.0, 110.0); 30 EleVertex ev = new EleVertex(p1, p2, p3); 31 32 List<EleVertex> list = ev.divide(); 33 34 assertEquals(2, list.size()); 35 36 // 1st vertex (p1, p2, pN 105m) 37 EleVertex v1 = list.get(0); 38 assertEquals(325 / 3D, v1.getEle()); 39 assertCoorEq(v1, 30D, 30D, 0); 40 assertCoorEq(v1, 30D, 35D, 1); 41 assertCoorEq(v1, 35D, 32.5D, 2); 42 43 // 2nd vertex (p3, p2, pN = 105m) 44 EleVertex v2 = list.get(1); 45 46 assertEquals(335/3D, v2.getEle()); 47 assertCoorEq(v2, 40D, 35D, 0); 48 assertCoorEq(v2, 30D, 35D, 1); 49 assertCoorEq(v2, 35D, 32.5D, 2); 48 50 } 49 51 50 52 public void testSimpleRecurse() { 51 52 53 54 55 56 57 58 53 EleCoordinate c1 = new EleCoordinate(new LatLon(50.8328, 8.1337), 300); 54 EleCoordinate c2 = new EleCoordinate(new LatLon(50.8328, 7.9217), 200); 55 EleCoordinate c3 = new EleCoordinate(new LatLon(50.9558, 7.9217), 400); 56 EleCoordinate c4 = new EleCoordinate(new LatLon(50.5767627, 9.1938483), 100); 57 58 EleVertex v1 = new EleVertex(c1, c2, c3); 59 System.out.println("Start recurse"); 60 recurse(v1, 0); 59 61 } 60 62 61 63 private void recurse(EleVertex v, int depth) { 62 63 64 65 66 67 assertTrue(depth < 50); //, "Too many recursions?"); 68 69 70 71 72 73 74 75 64 if (!v.isFinished() && depth <100) { 65 System.out.println("\tDivide: " + v); 66 List<EleVertex> list = v.divide(); 67 assertNotNull(list); 68 assertEquals(2, list.size()); 69 assertTrue(depth < 50); //, "Too many recursions?"); 70 for (EleVertex eleVertex : list) { 71 //System.out.println("\t\tRecurse: " + eleVertex); 72 assertTrue("Area is larger " + v.getArea() + " > " + eleVertex.getArea(), eleVertex.getArea() < v.getArea()); 73 recurse(eleVertex, depth + 1); 74 } 75 } else { 76 System.out.println("Finished: " + depth); 77 } 76 78 } 77 79 /* 78 80 public void testRenderer() { 79 80 81 82 83 new LatLon(50.6607106, 8.7337029), 84 85 86 81 82 // Staufenberg, Hessen 83 // Ulrichstein, Hessen 84 GridRenderer er = new GridRenderer("Ele", new Bounds( 85 new LatLon(50.6607106, 8.7337029), 86 new LatLon(50.5767627, 9.1938483)), null); 87 88 er.run(); 87 89 }*/ 88 90 89 91 public void testColorMap() { 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 assertEquals(Color.darkGray, c5); 92 ColorMap testMap = ColorMap.create("Test", new Color[]{Color.white, Color.black}, new int[]{0, 1000}); 93 94 // range test 95 Color c1 = testMap.getColor(-100); 96 assertEquals(Color.white, c1); 97 // range test 98 Color c2 = testMap.getColor(1100); 99 assertEquals(Color.black, c2); 100 // test mid (RGB 128, 128, 128) 101 Color c3 = testMap.getColor(500); 102 assertEquals(Color.gray, c3); 103 104 // test 0.75 (RGB 192 x 3) 105 Color c4 = testMap.getColor(751); 106 assertEquals(Color.lightGray, c4); 107 // test 0.25 (RGB 64 x 3) 108 Color c5 = testMap.getColor(251); 109 assertEquals(Color.darkGray, c5); 108 110 } 109 111 110 112 private void assertCoorEq(EleVertex v1, double x, double y, int n) { 111 112 113 assertEquals(x, v1.get(n).getX()); 114 assertEquals(y, v1.get(n).getY()); 113 115 } 114 116 } -
applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/HgtReaderTest.java
r29907 r30344 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.plugins.elevation.tests; 2 3 4 3 5 4 import junit.framework.TestCase; … … 15 14 * Setup test. 16 15 */ 16 @Override 17 17 public void setUp() { 18 18 Main.pref = new Preferences(); … … 20 20 21 21 public void testGetElevationFromHgt() { 22 23 24 25 26 27 22 // Staufenberg, Hessen 23 testHgtData(50.6607106, 8.7337029, "N50E008.hgt", 199); 24 // Ulrichstein, Hessen 25 testHgtData(50.5767627, 9.1938483, "N50E009.hgt", 560); 26 // Fujijama 27 //testHgtData(35.360555, 138.727777, "N35E138.hgt", 3741); 28 28 } 29 29 30 30 private void testHgtData(final double lat, final double lon, 31 32 33 34 35 36 37 38 39 40 41 42 31 final String expTag, final int expHeight) { 32 LatLon l = new LatLon(lat, lon); 33 HgtReader hr = new HgtReader(); 34 String text = hr.getHgtFileName(l); 35 36 assertEquals(expTag, text); 37 38 double d = hr.getElevationFromHgt(l); 39 System.out.println(d); 40 assertFalse("Data missing or void for coor " + l, Double.isNaN(d)); 41 42 assertEquals((int)d, expHeight); 43 43 } 44 44 }
Note:
See TracChangeset
for help on using the changeset viewer.