Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColoredElevationLayer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColoredElevationLayer.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ColoredElevationLayer.java	(revision 29907)
@@ -0,0 +1,108 @@
+package org.openstreetmap.josm.plugins.elevation;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+import java.awt.Color;
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.util.concurrent.BlockingDeque;
+
+import javax.swing.Action;
+import javax.swing.Icon;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.osm.visitor.BoundingXYVisitor;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
+import org.openstreetmap.josm.gui.layer.Layer;
+import org.openstreetmap.josm.plugins.elevation.gui.ElevationColors;
+import org.openstreetmap.josm.plugins.elevation.gui.Triangle;
+import org.openstreetmap.josm.tools.ImageProvider;
+
+public class ColoredElevationLayer extends Layer implements IEleRenderingListener {
+    private ElevationRenderer renderer;
+    
+
+    public ColoredElevationLayer(String name) {
+	super(name);
+
+	// 
+	setOpacity(0.5);
+    }
+
+    @Override
+    public void paint(Graphics2D g, MapView mv, Bounds box) {
+	if (renderer == null) {
+	    renderer = new ElevationRenderer(getName(), box, this);
+	    System.out.println("Start renderer...");
+	    Main.worker.submit(renderer);
+	}
+	
+	if (renderer.getVertices().size() > 0) {
+	    BlockingDeque<EleVertex> list = renderer.getVertices();
+	    for (EleVertex eleVertex : list) {
+		Point p0 = mv.getPoint(eleVertex.get(0));
+		Point p1 = mv.getPoint(eleVertex.get(1));
+		Point p2 = mv.getPoint(eleVertex.get(2));
+		Triangle t = new Triangle(p0, p1, p2);
+		
+		
+		//g.setColor(Color.magenta);
+		//g.draw(t);
+		g.setColor(ElevationColors.getElevationColor(eleVertex.getEle()));
+		g.fill(t);
+	    }
+	}
+    }
+
+    @Override
+    public Icon getIcon() {	
+	return ImageProvider.get("layer", "elevation_small");
+    }
+
+    @Override
+    public String getToolTipText() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    @Override
+    public void mergeFrom(Layer from) {
+	// TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public boolean isMergable(Layer other) {
+	// TODO Auto-generated method stub
+	return false;
+    }
+
+    @Override
+    public void visitBoundingBox(BoundingXYVisitor v) {
+	// TODO Auto-generated method stub
+
+    }
+
+    @Override
+    public Object getInfoComponent() {
+	// TODO Auto-generated method stub
+	return null;
+    }
+
+    @Override
+    public Action[] getMenuEntries() {
+	return new Action[] { new LayerListPopup.InfoAction(this) };
+    }
+
+    @Override
+    public void finished(EleVertex vertex) {
+	
+    }
+
+    @Override
+    public void finishedAll() {
+	Main.map.mapView.repaint();	
+    }
+
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleCoordinate.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleCoordinate.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleCoordinate.java	(revision 29907)
@@ -0,0 +1,38 @@
+package org.openstreetmap.josm.plugins.elevation;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+
+public class EleCoordinate extends LatLon {    
+    /**
+     * 
+     */
+    private static final long serialVersionUID = 9121465585197496570L;
+    
+    private double ele = Double.NaN; 
+
+    public EleCoordinate() {
+	this(Double.NaN, Double.NaN, Double.NaN);
+    }
+    
+    public EleCoordinate(double lat, double lon, double ele) {
+	super(lat, lon);
+	this.ele = ele;
+    }
+    
+    public EleCoordinate(LatLon latLon, double ele) {
+	this(latLon.lat(), latLon.lon(), ele);	
+    }
+
+    /**
+     * Gets the elevation in meter.
+     *
+     * @return the ele
+     */
+    public double getEle() {
+        return ele;
+    }
+  
+    public String toString() {
+        return "EleCoordinate[" + lat() + ", " + lon() + ", " + getEle() + "]";
+    }
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleVertex.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleVertex.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/EleVertex.java	(revision 29907)
@@ -0,0 +1,220 @@
+package org.openstreetmap.josm.plugins.elevation;
+
+import java.util.ArrayList;
+import java.util.Arrays;
+import java.util.List;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+
+public class EleVertex {
+    private static final int NPOINTS = 3;
+    private static final double MIN_DIST = 90;
+    
+    private double avrgEle = Double.NaN;
+    private double area = Double.NaN;
+    private EleCoordinate[] points = new EleCoordinate[NPOINTS];
+    
+    public EleVertex(EleCoordinate p1, EleCoordinate p2, EleCoordinate p3) {
+	points[0] = p1;
+	points[1] = p2;
+	points[2] = p3;
+	
+	// compute elevation
+	double z = 0D;
+	boolean eleValid = true;
+	for (EleCoordinate point : points) {
+	    if (ElevationHelper.isValidElevation(p1.getEle())) {
+		z += point.getEle();
+	    } else {
+		eleValid = false;
+		break;
+	    }
+	}
+	
+	if (eleValid) {	
+	    avrgEle = z / NPOINTS;
+	} else {
+	    avrgEle = ElevationHelper.NO_ELEVATION;
+	}
+	
+	// compute the (approx.!) area of the vertex using heron's formula
+	double a = p1.greatCircleDistance(p2);
+	double b = p2.greatCircleDistance(p3);
+	double c = p1.greatCircleDistance(p3);
+	
+	double s = (a + b + c) / 2D;
+	double sq = s * (s - a) * (s - b) * (s - c);
+	area = Math.sqrt(sq);
+    }
+    
+    public List<EleVertex> divide() {
+	TriangleEdge[] edges = new TriangleEdge[NPOINTS];
+	
+	int k = 0;
+	for (int i = 0; i < points.length; i++) {
+	    EleCoordinate c1 = points[i];
+	    
+	    for (int j = i + 1; j < points.length; j++) {
+		EleCoordinate c2 = points[j];
+		
+		edges[k++] = new TriangleEdge(i, j, c1.greatCircleDistance(c2));
+	    }
+	}
+
+	/*
+	for (int i = 0; i < edges.length; i++) {
+	    TriangleEdge triangleEdge = edges[i];
+	    System.out.println("#" + i + ": " +triangleEdge);
+	}*/
+	
+	// sort by distance
+	Arrays.sort(edges);
+	// pick the longest edge
+	TriangleEdge longest = edges[0];
+	
+	
+	//System.out.println("Longest " + longest);
+	EleCoordinate pI = points[longest.getI()];
+	EleCoordinate pJ = points[longest.getJ()];
+	EleCoordinate pK = points[longest.getK()];
+	EleCoordinate newP = getMid(pI, pJ);
+	/*
+	System.out.println(pI);
+	System.out.println(pJ);
+	System.out.println(pK);
+	System.out.println(newP);
+	*/
+	List<EleVertex> res = new ArrayList<EleVertex>();
+	res.add(new EleVertex(pI, pK, newP));
+	res.add(new EleVertex(pJ, pK, newP));
+	
+	return res;
+    }
+    
+    /**
+     * Checks if vertex requires further processing or is finished. Currently this
+     * method returns <code>true</code>, if the average deviation is < 5m 
+     *
+     * @return true, if is finished
+     */
+    public boolean isFinished() {
+	double z = 0D;
+	double avrgEle = getEle();
+	
+	for (EleCoordinate point : points) {
+	    z += (avrgEle - point.getEle()) * (avrgEle - point.getEle());
+	}
+	
+	// TODO: Check for proper limit
+	return z < 75 || getArea() < (30 * 30); // = 3 * 25
+    }    
+    
+    /**
+     * Gets the approximate area of this vertex in square meters.
+     *
+     * @return the area
+     */
+    public double getArea() {
+        return area;
+    }
+
+    /**
+     * Gets the (linear interpolated) mid point of c1 and c2.
+     *
+     * @param c1 the first coordinate
+     * @param c2 the second coordinate
+     * @return the mid point
+     */
+    public EleCoordinate getMid(EleCoordinate c1, EleCoordinate c2) {
+	double x = (c1.getX() + c2.getX()) / 2.0;
+	double y = (c1.getY() + c2.getY()) / 2.0;
+	
+	double z = (c1.getEle() + c2.getEle()) / 2.0;
+	if (c1.greatCircleDistance(c2) > MIN_DIST) {
+	    double hgtZ = ElevationHelper.getElevation(new LatLon(y, x));
+	    
+	    if (ElevationHelper.isValidElevation(hgtZ)) {
+		z = hgtZ;
+	    }	    
+    	}
+	
+	return new EleCoordinate(y, x, z);
+    }
+    
+    /**
+     * Gets the coordinate for the given index.
+     *
+     * @param index the index between 0 and NPOINTS: 
+     * @return the elevation coordinate instance
+     * @throws IllegalArgumentException, if index is invalid
+     */
+    public EleCoordinate get(int index) {
+	if (index < 0 || index >= NPOINTS) throw new IllegalArgumentException("Invalid index: " + index);
+	
+	return points[index];
+    }
+    
+    /**
+     * Gets the average elevation of this vertex.
+     *
+     * @return the ele
+     */
+    public double getEle() {
+	
+	return avrgEle;
+    }
+    
+    @Override
+    public String toString() {
+	return "EleVertex [avrgEle=" + avrgEle + ", area=" + area + ", points="
+		+ Arrays.toString(points) + "]";
+    }
+
+
+
+
+    class TriangleEdge implements Comparable<TriangleEdge> {
+	private int i;
+	private int j;
+	private double dist;
+	
+	public TriangleEdge(int i, int j, double dist) {
+	    super();
+	    this.i = i;
+	    this.j = j;
+	    this.dist = dist;
+	}
+
+	public int getI() {
+	    return i;
+	}
+
+	public int getJ() {
+	    return j;
+	}
+	
+	public int getK() {
+	    if (i == 0) {
+		return j == 1 ? 2 : 1;
+	    } else if (i == 1) {
+		return j == 0 ? 2 : 0;
+	    } else {
+		return j == 0 ? 1 : 0;
+	    }
+	}
+
+	public double getDist() {
+	    return dist;
+	}
+
+	@Override
+	public int compareTo(TriangleEdge o) {
+	    return (int) (o.getDist() - dist);
+	}
+
+	@Override
+	public String toString() {
+	    return "TriangleEdge [i=" + i + ", j=" + j + ", dist=" + dist + "]";
+	}
+    }
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationHelper.java	(revision 29907)
@@ -0,0 +1,374 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation;
+
+import java.util.ArrayList;
+import java.util.Calendar;
+import java.util.GregorianCalendar;
+import java.util.List;
+import java.util.Locale;
+
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.gpx.GeoidCorrectionKind;
+
+/**
+ * Provides methods to access way point attributes and some utility methods regarding elevation stuff (
+ * e. g. special text formats, unit conversion, geoid calc).
+ * @author Oliver Wieland <oliver.wieland@online.de> 
+ */
+public class ElevationHelper {
+	public static double METER_TO_FEET = 3.280948;
+	
+	/* Countries which use the imperial system instead of the metric system. */
+	private static String IMPERIAL_SYSTEM_COUNTRIES[] = {
+		"en_US", 	/* USA */
+		"en_CA",	/* Canada */
+		"en_AU",	/* Australia */
+		"en_NZ",	/* New Zealand */
+//		"de_DE",	/* for testing only */
+		"en_ZA"	/* South Africa */
+	};
+	
+	/** The 'no elevation' data magic. */
+	public static double NO_ELEVATION = Double.NaN;
+	
+	/**
+	 * The name of the elevation height of a way point.
+	 */
+	public static final String HEIGHT_ATTRIBUTE = "ele";
+	
+	private static UnitMode unitMode = UnitMode.NotSelected;
+		
+	private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None;
+	
+	/** The HGT reader instance. */
+	private static HgtReader hgt = new HgtReader();
+	
+	/**
+	 * Gets the current mode of GEOID correction.
+	 * @return
+	 */
+	public static GeoidCorrectionKind getGeoidKind() {
+		return geoidKind;
+	}
+
+	public static void setGeoidKind(GeoidCorrectionKind geoidKind) {
+		ElevationHelper.geoidKind = geoidKind;
+	}
+	
+	/**
+	 * Gets the current unit mode (metric or imperial).
+	 * @return
+	 */
+	public static UnitMode getUnitMode() {
+		//TODO: Use this until /JOSM/src/org/openstreetmap/josm/gui/NavigatableComponent.java 
+		// has a an appropriate method 
+		
+		// unit mode already determined?
+		if (unitMode != UnitMode.NotSelected) {
+			return unitMode;
+		}
+		
+		// Set default
+		unitMode = UnitMode.Metric;
+		
+		// Check if user could prefer imperial system 
+		Locale l = Locale.getDefault();		
+		for (int i = 0; i < IMPERIAL_SYSTEM_COUNTRIES.length; i++) {
+			String ctry = l.toString();
+			if (IMPERIAL_SYSTEM_COUNTRIES[i].equals(ctry)) {
+				unitMode = UnitMode.Imperial;
+			}
+		}
+		
+		return unitMode;
+	}
+	
+	/**
+	 * Gets the unit string for elevation ("m" or "ft").
+	 * @return
+	 */
+	public static String getUnit() {		
+		switch (getUnitMode()) {
+		case Metric:
+			return "m";
+		case Imperial:
+			return "ft";
+		default:
+			throw new RuntimeException("Invalid or unsupported unit mode: " + unitMode);
+		}
+	}
+	
+	/**
+	 * Checks if given value is a valid elevation value.
+	 *
+	 * @param ele the ele
+	 * @return true, if is valid elevation
+	 */
+	public static boolean isValidElevation(double ele) {
+	    return !Double.isNaN(ele);
+	}
+	
+	/**
+	 * Gets the elevation (Z coordinate) of a GPX way point in meter or feet (for
+	 * US, UK, ZA, AU, NZ and CA). 
+	 * 
+	 * @param wpt
+	 *            The way point instance.
+	 * @return The x coordinate or <code>NO_ELEVATION</code>, if the given way point is null or contains
+	 *         not height attribute.
+	 */
+	public static double getElevation(WayPoint wpt) {
+	    if (wpt == null) return NO_ELEVATION;
+	    
+	    // try to get elevation from HGT file
+	    double eleInt = getInternalElevation(wpt.getCoor());	    
+	    if (isValidElevation(eleInt)) {
+		return convert(eleInt);
+	    }
+	    
+	    // no HGT, check for elevation data in GPX
+	    if (!wpt.attr.containsKey(HEIGHT_ATTRIBUTE)) {
+		// GPX has no elevation data :-(
+		return NO_ELEVATION;
+	    }
+
+	    // Parse elevation from GPX data
+	    String height = wpt.getString(ElevationHelper.HEIGHT_ATTRIBUTE);
+	    try {
+		double z = Double.parseDouble(height);
+
+		return convert(z);
+	    } catch (NumberFormatException e) {
+		System.err.println(String.format(
+			"Cannot parse double from '%s': %s", height, e
+			.getMessage()));
+		return NO_ELEVATION;
+	    }
+	}
+	
+	
+	public static double getElevation(LatLon ll) {
+		double ele = getInternalElevation(ll);
+		//System.out.println("Get elevation " + ll + " => " + ele);
+		return convert(ele);
+	}
+
+	/**
+	 * Converts the value to feet, if required.
+	 *
+	 * @param ele the elevation to convert
+	 * @return the double
+	 */
+	private static double convert(double ele) {
+	    if (isValidElevation(ele)) {
+	        if (getUnitMode() == UnitMode.Imperial) {
+	    		// translate to feet
+	    		return meter2Feet(ele);
+	        } else {
+	            // keep 'as is'
+	            return ele;
+	        }
+	    } 
+	    return NO_ELEVATION;	    
+	}
+	
+	/**
+	 * Computes the slope <b>in percent</b> between two way points. E. g. an elevation gain of 12m 
+	 * within a distance of 100m is equal to a slope of 12%. 
+	 *
+	 * @param w1 the first way point
+	 * @param w2 the second way point
+	 * @return the slope in percent
+	 */
+	public static double computeSlope(LatLon w1, LatLon w2) {
+	    	// same coordinates? -> return 0, if yes
+	    	if (w1.equals(w2)) return 0;
+	    
+		// get distance in meters and divide it by 100 in advance
+		double distInMeter = convert(w1.greatCircleDistance(w2) / 100.0);
+		
+		// get elevation (difference) - is converted automatically to feet
+		int ele1 = (int) ElevationHelper.getElevation(w1);
+		int ele2 = (int) ElevationHelper.getElevation(w2);
+		int dH = ele2 - ele1;
+		
+		// Slope in percent is define as elevation gain/loss in meters related to a distance of 100m
+		return dH / distInMeter;
+	}
+	
+	/**
+	 * Converts meter into feet
+	 *
+	 * @param meter the meter
+	 * @return the double
+	 */
+	public static double meter2Feet(double meter) {
+	    return meter * METER_TO_FEET;
+	}
+	
+	/**
+	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
+	 * @param elevation
+	 * @return
+	 */
+	public static String getElevationText(int elevation) {
+		return String.format("%d %s", elevation, getUnit());
+	}
+	
+	/**
+	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
+	 * @param elevation
+	 * @return
+	 */
+	public static String getElevationText(double elevation) {
+		return String.format("%d %s", (int)Math.round(elevation), getUnit());
+	}
+	
+	/**
+	 * Gets the elevation string for a given way point, e. g "300m" or "800ft".
+	 *
+	 * @param wpt the way point
+	 * @return the elevation text
+	 */
+	public static String getElevationText(WayPoint wpt) {
+		return getElevationText(wpt.getCoor());
+	}
+	
+	/**
+	 * Gets the elevation string for a given coordinate, e. g "300m" or "800ft".
+	 *
+	 * @param coor the coordinate
+	 * @return the elevation text
+	 */
+	public static String getElevationText(LatLon coor) {
+		if (coor == null) return null;
+		
+		int elevation = (int)Math.round(ElevationHelper.getElevation(coor));
+		return String.format("%d %s", (int)elevation, getUnit());
+	}
+	
+	/**
+	 * Get the time string for a given way point.
+	 * @param wpt
+	 * @return
+	 */
+	public static String getTimeText(WayPoint wpt) {
+		if (wpt == null) return null; 
+		
+		int hour = ElevationHelper.getHourOfWayPoint(wpt);
+		int min = ElevationHelper.getMinuteOfWayPoint(wpt);		
+		return String.format("%02d:%02d", hour, min);
+	}
+
+	/**
+	 * Gets the elevation (Z coordinate) of a GPX way point.
+	 * 
+	 * @param ll
+	 *            The way point instance.
+	 * @return The x coordinate or 0, if the given way point is null or contains
+	 *         not height attribute.
+	 */
+	private static double getInternalElevation(LatLon ll) {
+		if (ll != null) {
+		    	// Try to read data from SRTM file
+		    	// TODO: Option to switch this off
+		    	double eleHgt = hgt.getElevationFromHgt(ll);
+		    	
+		    	System.out.println("Get elevation from HGT " + ll + " => " + eleHgt);
+		    	if (isValidElevation(eleHgt)) {		    	    
+		    	    return eleHgt;
+		    	}
+		}
+		return NO_ELEVATION;
+	}
+
+	/*
+	 * Gets the geoid height for the given way point. See also {@link
+	 * GeoidData}.
+	 */
+	public static byte getGeoidCorrection(WayPoint wpt) {
+	    	/*
+		int lat = (int)Math.round(wpt.getCoor().lat());
+		int lon = (int)Math.round(wpt.getCoor().lon());
+		byte geoid = GeoidData.getGeoid(lat, lon);
+		
+		System.out.println(
+				String.format("Geoid(%d, %d) = %d", lat, lon, geoid));
+	    	 */
+		return 0;
+	}
+
+	/**
+	 * Reduces a given list of way points to the specified target size.
+	 * 
+	 * @param origList
+	 *            The original list containing the way points.
+	 * @param targetSize
+	 *            The desired target size of the list. The resulting list may
+	 *            contain fewer items, so targetSize should be considered as
+	 *            maximum.
+	 * @return A list containing the reduced list.
+	 */
+	public static List<WayPoint> downsampleWayPoints(List<WayPoint> origList,
+			int targetSize) {
+		if (origList == null)
+			return null;
+		if (targetSize <= 0)
+			throw new IllegalArgumentException(
+					"targetSize must be greater than zero");
+
+		int origSize = origList.size();
+		if (origSize <= targetSize) {
+			return origList;
+		}
+
+		int delta = (int) Math.max(Math.ceil(origSize / targetSize), 2);
+
+		List<WayPoint> res = new ArrayList<WayPoint>(targetSize);
+		for (int i = 0; i < origSize; i += delta) {
+			res.add(origList.get(i));
+		}
+
+		return res;
+	}
+	
+	/**
+	 * Gets the hour value of a way point in 24h format.
+	 * @param wpt
+	 * @return
+	 */
+	public static int getHourOfWayPoint(WayPoint wpt) {
+		if (wpt == null) return -1;
+		
+		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
+		calendar.setTime(wpt.getTime());   // assigns calendar to given date 
+		return calendar.get(Calendar.HOUR_OF_DAY); 
+	}
+	
+	/**
+	 * Gets the minute value of a way point in 24h format.
+	 * @param wpt
+	 * @return
+	 */
+	public static int getMinuteOfWayPoint(WayPoint wpt) {
+		if (wpt == null) return -1;
+		
+		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
+		calendar.setTime(wpt.getTime());   // assigns calendar to given date 
+		return calendar.get(Calendar.MINUTE); 
+	}
+}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationModel.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationModel.java	(revision 29906)
+++ 	(revision )
@@ -1,239 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxRoute;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
-import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Represents the top-level part of the elevation model. The elevation model
- * breaks done into the tracks/routes of a GPX file (see
- * {@link ElevationProfileNode}). Each track is divided into 'slices' (see
- * {@link ElevationProfileLeaf}) - a set of fixed number of way points. This
- * structure allows as well an overview over a single track as a detailed
- * elevation view of a track part.
- * 
- * @see ElevationProfileNode
- * @see ElevationProfileLeaf
- * @see IElevationModelTrackListener
- * @see IElevationModelSliceListener
- * @author Oliver Wieland <oliver.wieland@online.de>
- */
-public class ElevationModel extends ElevationProfileBase implements IGpxVisitor {
-	// private int sliceSize;
-	private int trackCounter;
-	private GpxData gpxData;
-
-	private List<IElevationProfile> tracks;
-	private List<WayPoint> buffer = new ArrayList<WayPoint>(1000);
-	private List<WayPoint> tmpWaypoints = new ArrayList<WayPoint>(1000);
-
-	private List<IElevationModelListener> listeners = new ArrayList<IElevationModelListener>();
-
-	public ElevationModel() {
-		this("", null, 100);
-	}
-
-	public ElevationModel(String name, GpxData data, int sliceSize) {
-		super(name);
-		gpxData = data;
-		setSliceSize(Math.max(sliceSize, 100));
-	}
-
-	@Override
-	public void setSliceSize(int sliceSize) {
-
-		super.setSliceSize(sliceSize);
-
-		// FIXME: Listener should go in base class
-		updateElevationData();
-		fireModelChanged();
-	}
-
-	/**
-	 * Gets the GPX data instance used by this model.
-	 * 
-	 * @return
-	 */
-	public GpxData getGpxData() {
-		return gpxData;
-	}
-	
-	/**
-	 * @return the tracks
-	 */
-	protected List<IElevationProfile> getTracks() {
-		return tracks;
-	}
-
-	/**
-	 * Gets a flag indicating whether the associated way points contained
-	 * elevation data or not. This is the case if min and max height or both
-	 * zero.
-	 * 
-	 * @return
-	 */
-	public boolean hasElevationData() {
-		return getMaxHeight() != getMinHeight();
-	}
-
-	/**
-	 * Fires the 'model changed' event to all listeners.
-	 */
-	protected void fireModelChanged() {
-		for (IElevationModelListener listener : listeners) {
-			listener.elevationProfileChanged(this);
-		}
-	}
-
-	/**
-	 * Adds a model listener to this instance.
-	 * 
-	 * @param listener
-	 *            The listener to add.
-	 */
-	public void addModelListener(IElevationModelListener listener) {
-		this.listeners.add(listener);
-	}
-
-	/**
-	 * Removes a model listener from this instance.
-	 * 
-	 * @param listener
-	 *            The listener to remove.
-	 */
-	public void removeModelListener(IElevationModelListener listener) {
-		this.listeners.remove(listener);
-	}
-
-	/**
-	 * Removes all listeners from this instance.
-	 */
-	public void removeAllListeners() {
-		this.listeners.clear();
-	}
-
-	/**
-	 * (Re)computes the elevation model.
-	 */
-	private void computeProfile() {
-		if (gpxData == null)
-			return; // nothing to do
-
-		trackCounter = 0;
-
-		super.updateValues();
-		if (tracks == null) {
-			tracks = new ArrayList<IElevationProfile>();
-		} else {
-			tmpWaypoints.clear();
-			buffer.clear();
-			tracks.clear();
-		}
-
-		setDistance(gpxData.length());	// get distance from GPX 
-		GpxIterator.visit(gpxData, this);
-
-		// reduce data
-		setWayPoints(WayPointHelper.downsampleWayPoints(tmpWaypoints,
-				getSliceSize()), false);
-	}
-
-	/**
-	 * Forces the model to refresh itself. Clients (e. g. UI widgets) may use
-	 * this method to notify the model on UI changes.
-	 */
-	public void updateElevationData() {
-		computeProfile();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IGpxVisitor#visit(org.openstreetmap
-	 * .josm.data.gpx.GpxRoute, org.openstreetmap.josm.data.gpx.WayPoint)
-	 */
-	public void visit(GpxRoute route, WayPoint wp) {
-		processWayPoint(wp);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IGpxVisitor#visit(org.openstreetmap
-	 * .josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment,
-	 * org.openstreetmap.josm.data.gpx.WayPoint)
-	 */
-	public void visit(GpxTrack track, GpxTrackSegment segment, WayPoint wp) {
-		processWayPoint(wp);
-	}
-	
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#visit(org.openstreetmap.josm.data.gpx.WayPoint)
-	 */
-	@Override
-	public void visit(WayPoint wp) {
-		super.visit(wp);
-		processWayPoint(wp);
-	}
-
-	public void start() {
-		buffer.clear();
-	}
-
-	public void end() {
-		String trackName = "Track#" + trackCounter;
-		addTrackOrRoute(trackName);		
-	}
-	
-	private void addTrackOrRoute(String trackName) {
-		if (getSliceSize() > 0) {
-			ElevationProfileNode emt = new ElevationProfileNode(trackName,
-					this, buffer, getSliceSize());
-			tracks.add(emt);
-		}
-		trackCounter++;
-		buffer.clear();
-	}
-
-	private void processWayPoint(WayPoint wp) {
-		if (wp == null) {
-			throw new RuntimeException("WPT must not be null!");
-		}
-		
-		buffer.add(wp);
-		tmpWaypoints.add(wp);
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#getChildren
-	 * ()
-	 */
-	@Override
-	public List<IElevationProfile> getChildren() {
-		return tracks;
-	}
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileBase.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileBase.java	(revision 29906)
+++ 	(revision )
@@ -1,516 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Base class for an elevation profile. An elevation profile is constructed out
- * of a set of way points. The profile computes min/max/average height from the
- * full way point set and then reduces the number of way points to a given
- * amount, if necessary.
- * 
- * The computation is done via implementing {@link IGpxWaypointVisitor},
- * subclasses may override the {@link ElevationProfileBase#visit(WayPoint)}
- * method to compute own values or run specific actions. The computation is
- * triggered by calling {@link ElevationProfileBase#updateValues()}.
- * 
- * Elevation profiles can break down into further child profiles. This is
- * intended to show different levels of details, if the number of way points
- * exceed the display space (which is usually the case).
- * 
- * {@link IElevationProfile} {@link IGpxWaypointVisitor} {@link GpxIterator}
- * 
- * @author Oliver Wieland <oliver.wieland@online.de>
- * 
- */
-public abstract class ElevationProfileBase implements IElevationProfile,
-		IGpxWaypointVisitor {
-	public static final int WAYPOINT_START = 0;
-	public static final int WAYPOINT_END = 1;
-	public static final int WAYPOINT_MIN = 2;
-	public static final int WAYPOINT_MAX = 3;
-
-	private String name;
-	private int minHeight;
-	private int maxHeight;
-	private int avrgHeight;
-	private double dist;
-	private Date start = new Date();
-	private Date end = new Date();
-	private WayPoint[] importantWayPoints = new WayPoint[4];
-	private IElevationProfile parent;
-	private int sumEle; // temp var for average height
-	private List<WayPoint> wayPoints;
-	private int numWayPoints; // cached value
-	private int sliceSize;
-	private int gain;
-	private int lastEle;
-	private static boolean ignoreZeroHeight = true;
-
-	/**
-	 * Creates a name elevation profile without any way points.
-	 * 
-	 * @param name
-	 */
-	public ElevationProfileBase(String name) {
-		this(name, null, null, 0);
-	}
-
-	/**
-	 * Creates a name elevation profile with a given set of way points.
-	 * 
-	 * @param name
-	 *            The name of the profile.
-	 * @param parent
-	 *            The (optional) parent profile.
-	 * @param wayPoints
-	 *            The list containing the way points of the profile.
-	 * @param sliceSize
-	 *            The requested target size of the profile.
-	 */
-	public ElevationProfileBase(String name, IElevationProfile parent,
-			List<WayPoint> wayPoints, int sliceSize) {
-		super();
-		this.name = name;
-		this.parent = parent;
-		this.sliceSize = sliceSize;
-		setWayPoints(wayPoints, true);
-	}
-
-	public static boolean isIgnoreZeroHeight() {
-		return ignoreZeroHeight;
-	}
-
-	public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) {
-		ElevationProfileBase.ignoreZeroHeight = ignoreZeroHeight;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#invalidateModel
-	 * (int)
-	 */
-	public void updateElevationData() {
-		updateValues();
-	}
-
-	/**
-	 * Revisits all way points and recomputes the characteristic values like
-	 * min/max elevation.
-	 */
-	protected void updateValues() {
-		if (wayPoints == null)
-			return;
-		
-		int n = this.wayPoints.size(); 
-		if (n == 0)
-			return;
-
-		start = new Date();		
-		end = new Date(0L);
-		this.minHeight = Integer.MAX_VALUE;
-		this.maxHeight = Integer.MIN_VALUE;
-		sumEle = 0;
-		gain = 0;
-		lastEle = 0;
-		
-		for (WayPoint wayPoint : this.wayPoints) {
-			visit(wayPoint);
-		}
-		
-		if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) {
-			// file does not contain elevation data	at all
-			minHeight = 0;
-			maxHeight = 0;
-			setMinWayPoint(wayPoints.get(0));
-			setMaxWayPoint(wayPoints.get(n-1));
-		}		
-		
-		//if (start.after(end) || start.equals(end)) {
-			// GPX does not contain time stamps -> use sequential order
-			setStart(wayPoints.get(0));
-			setEnd(wayPoints.get(n-1));
-		//}
-		
-		avrgHeight = sumEle / n;
-	}
-
-	/**
-	 * Gets the name of the profile. 
-	 */
-	public String getName() {
-		return name;
-	}
-
-	/**
-	 * Sets the name of the profile.
-	 * @param name The new name of the profile.
-	 */
-	public void setName(String name) {
-		this.name = name;
-	}
-
-	/**
-	 * Sets the way point with the lowest elevation.
-	 * @param wp The way point instance having the lowest elevation.
-	 */
-	protected void setMinWayPoint(WayPoint wp) {
-		importantWayPoints[WAYPOINT_MIN] = wp;
-		this.minHeight = (int) WayPointHelper.getElevation(wp);
-	}
-
-	/**
-	 * Sets the way point with the highest elevation.
-	 * @param wp The way point instance having the highest elevation.
-	 */
-	protected void setMaxWayPoint(WayPoint wp) {
-		importantWayPoints[WAYPOINT_MAX] = wp;
-		this.maxHeight = (int) WayPointHelper.getElevation(wp);
-	}
-
-	/**
-	 * Sets the average height.
-	 * @param avrgHeight
-	 */
-	protected void setAvrgHeight(int avrgHeight) {
-		this.avrgHeight = avrgHeight;
-	}
-
-	/**
-	 * Sets the very first way point. 
-	 * @param wp
-	 */
-	protected void setStart(WayPoint wp) {
-		importantWayPoints[WAYPOINT_START] = wp;
-		this.start = wp.getTime();
-	}
-
-	/**
-	 * Sets the very last way point.
-	 * @param wp
-	 */
-	protected void setEnd(WayPoint wp) {
-		importantWayPoints[WAYPOINT_END] = wp;
-		this.end = wp.getTime();
-	}
-
-	public void setParent(IElevationProfile parent) {
-		this.parent = parent;
-	}
-
-	/**
-	 * Sets the way points of this profile.
-	 * 
-	 * @param wayPoints
-	 */
-	public void setWayPoints(List<WayPoint> wayPoints, boolean revisit) {
-		if (this.wayPoints != wayPoints) {
-			this.wayPoints = new ArrayList<WayPoint>(wayPoints);
-			numWayPoints = wayPoints != null ? wayPoints.size() : 0;
-			if (revisit) {				
-				updateValues();
-			}
-		}
-	}
-
-	/**
-	 * Checks if the given index is valid or not.
-	 * 
-	 * @param index
-	 *            The index to check.
-	 * @return true, if the given index is valid; otherwise false.
-	 */
-	protected boolean checkIndex(int index) {
-		return index >= 0 && index < getNumberOfWayPoints();
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#elevationValueAt
-	 * (int)
-	 */
-	public int elevationValueAt(int i) {
-		if (checkIndex(i)) {
-			return (int) WayPointHelper.getElevation(wayPoints.get(i));
-		} else {
-			throw new IndexOutOfBoundsException(String.format(
-					"Invalid index: %d, expected 0..%d", i,
-					getNumberOfWayPoints()));
-		}
-	}
-
-	/**
-	 * Gets the slice size for the detail view.
-	 * 
-	 * @return
-	 */
-	public int getSliceSize() {
-		return sliceSize;
-	}
-
-	/**
-	 * Sets the desired size of the elevation profile.
-	 */
-	public void setSliceSize(int sliceSize) {
-		if (this.sliceSize != sliceSize) {
-			this.sliceSize = sliceSize;
-		}
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getAverageHeight
-	 * ()
-	 */
-	public int getAverageHeight() {
-		return avrgHeight;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getChildren()
-	 */
-	public abstract List<IElevationProfile> getChildren();
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEnd()
-	 */
-	public Date getEnd() {
-		return end;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxHeight()
-	 */
-	public int getMaxHeight() {
-		return maxHeight;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinHeight()
-	 */
-	public int getMinHeight() {
-		return minHeight;
-	}
-
-	/**
-	 * Gets the difference between min and max elevation.
-	 * 
-	 * @return
-	 */
-	public int getHeightDifference() {
-		return maxHeight - minHeight;		
-	}
-	
-	/**
-	 * Gets the elevation gain.
-	 * 
-	 * @return
-	 */
-	public int getGain() {
-		return gain;
-	}
-	
-	
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getDistance()
-	 */
-	@Override
-	public double getDistance() {
-		return dist; // dist is in meters
-	}
-	
-	/**
-	 * Sets the distance of the elevation profile.
-	 * @param dist
-	 */
-	protected void setDistance(double dist) {
-		this.dist = dist; 
-	}
-
-	/**
-	 * Returns the time between start and end of the track.
-	 * @return
-	 */
-	public long getTimeDifference() {
-		WayPoint wp1 = getStartWayPoint();
-		WayPoint wp2 = getEndWayPoint();
-		
-		if (wp1 != null && wp2 != null) {
-			long diff = wp2.getTime().getTime() - wp1.getTime().getTime();
-			return diff;
-		}
-		
-		return 0L;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getParent()
-	 */
-	public IElevationProfile getParent() {
-		return parent;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStart()
-	 */
-
-	public Date getStart() {
-		return start;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEndWayPoint
-	 * ()
-	 */
-
-	public WayPoint getEndWayPoint() {
-		return importantWayPoints[WAYPOINT_END];
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxWayPoint
-	 * ()
-	 */
-
-	public WayPoint getMaxWayPoint() {
-		return importantWayPoints[WAYPOINT_MAX];
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinWayPoint
-	 * ()
-	 */
-
-	public WayPoint getMinWayPoint() {
-		return importantWayPoints[WAYPOINT_MIN];
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStartWayPoint
-	 * ()
-	 */
-	public WayPoint getStartWayPoint() {
-		return importantWayPoints[WAYPOINT_START];
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @see
-	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getWayPoints()
-	 */
-	public List<WayPoint> getWayPoints() {
-		return wayPoints;
-	}
-
-	/*
-	 * (non-Javadoc)
-	 * 
-	 * @seeorg.openstreetmap.josm.plugins.elevation.ElevationProfileBase#
-	 * getNumberOfWayPoints()
-	 */
-	public int getNumberOfWayPoints() {
-		return numWayPoints;// wayPoints != null ? wayPoints.size() : 0;
-	}
-
-	/**
-	 * Gets a flag indicating whether the associated way points contained
-	 * elevation data or not. This is the case if min and max height or both
-	 * zero.
-	 * 
-	 * @return
-	 */
-	public boolean hasElevationData() {
-		return minHeight != maxHeight;
-	}
-
-	/**
-	 * Visits a way point in order to update statistical values about the given
-	 * way point list.
-	 */
-	public void visit(WayPoint wp) {
-		if (wp.getTime().after(end)) {
-			setEnd(wp);
-		}
-
-		if (wp.getTime().before(start)) {
-			setStart(wp);
-		}
-
-		int ele = (int) WayPointHelper.getElevation(wp);
-
-		if (!isIgnoreZeroHeight() || ele > 0) {
-			if (ele > maxHeight) {
-				setMaxWayPoint(wp);
-			}
-			if (ele < minHeight) {
-				setMinWayPoint(wp);
-			}
-			
-			if (ele > lastEle) {
-				gain += ele - lastEle;
-			}
-
-			sumEle += ele;
-			lastEle = ele;			
-		}
-	}
-	
-	public String toString() {
-		return "ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
-				+ ", minHeight=" + getMinHeight() + ", maxHeight="
-				+ getMaxHeight() + "]";
-	}
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileLeaf.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileLeaf.java	(revision 29906)
+++ 	(revision )
@@ -1,62 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.List;
-
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * This class represents a 'leaf node' in the elevation profile tree. It has no children and ignores
- * the slice size parameter. So no data reduction takes places; every way point is kept.   
- * 
- * ElevationModelSlice is intended to be used internally.
- * @author Oliver Wieland <oliver.wieland@online.de>
- *
- */
-public class ElevationProfileLeaf extends ElevationProfileBase {
-	/**
-	 * Creates a name elevation profile leaf with a given set of way points.
-	 * @param name The name of the profile.
-	 * @param parent The (optional) parent profile.
-	 * @param wayPoints The list containing the way points of the profile.
-	 */
-	public ElevationProfileLeaf(String name, IElevationProfile parent, List<WayPoint> wayPoints) {
-		super(name, parent, wayPoints, 0);		
-	}
-
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#elevationValueAt(int)
-	 */
-	@Override
-	public int elevationValueAt(int i) {
-		if (i < 0 || i >= getNumberOfWayPoints()) throw new IndexOutOfBoundsException("Wrong index: " + i);
-		return (int)WayPointHelper.getElevation(getWayPoints().get(i));
-	}
-
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getChildren()
-	 */
-	@Override
-	public List<IElevationProfile> getChildren() {
-		return null; // we have no children
-	}
-	
-	@Override
-	public String toString() {
-		return "ElevationModelSlice [avrgEle=" + getAverageHeight() + ", maxEle=" + getMaxHeight()
-				+ ", minEle=" + getMinHeight() + ", name=" + getName() + ", wayPoints="
-				+ getNumberOfWayPoints() + "]";
-	}
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileNode.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfileNode.java	(revision 29906)
+++ 	(revision )
@@ -1,124 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.ArrayList;
-import java.util.List;
-
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Represents a elevation model of a single GPX track, route or collection of
- * way points. It usually breaks down into many slices represented by 
- * {@link ElevationProfileLeaf} which are accessible via {@link ElevationProfileBase#getChildren()}.
- * 
- * @author Oliver Wieland <oliver.wieland@online.de>
- * 
- * @see ElevationProfileBase
- * @see ElevationModel
- * @see ElevationProfileLeaf
- */
-public class ElevationProfileNode extends ElevationProfileBase {
-	private List<IElevationProfile> slices;
-	
-	/**
-	 * Creates a new elevation track model.
-	 * @param trackName The name of the track.
-	 * @param parent The parent elevation profile
-	 * @param sliceSize The (maximum) size of each slice.
-	 * @param wayPoints The way points belonging to this track.
-	 */
-	public ElevationProfileNode(String trackName, IElevationProfile parent, List<WayPoint> wayPoints, int sliceSize) {
-		super(trackName, parent, wayPoints, sliceSize);
-		setSliceSize(sliceSize);
-		// ensure that sliceSize has a reasonable value
-		createsSlices(wayPoints);
-	}
-
-	/**
-	 * Notifies listeners that the active slice has been changed.
-	 * 
-	 * @param oldIndex
-	 *            The index of the previously selected slice.
-	 * @param newIndex
-	 *            The index of the current slice.
-	 * 
-	 *            private void fireSliceChanged(int oldIndex, int newIndex) { if
-	 *            (listeners == null || listeners.size() == 0) { return; }
-	 * 
-	 *            if (!checkIndex(newIndex)) { throw new
-	 *            IndexOutOfBoundsException(
-	 *            String.format("Invalid index: %d (expected 0-%d)", newIndex,
-	 *            getNumberOfSlices())); } ElevationModelSlice oldObj =
-	 *            getSliceAt(oldIndex); ElevationModelSlice newObj =
-	 *            getSliceAt(newIndex);
-	 * 
-	 *            for (IElevationModelSliceListener listener : listeners) {
-	 *            listener.sliceSelectionChanged(oldObj, newObj); } }
-	 */
-
-	/**
-	 * Gets the number of slices.
-	 * 
-	 * @return
-	 */
-	public int getNumberOfSlices() {
-		return slices != null ? slices.size() : 0;
-	}
-
-	/**
-	 * Assign other way points to this track.
-	 * 
-	 * @param waypoints
-	 *            The list containing the way points.
-	 */
-	public void updateTrack(List<WayPoint> waypoints) {
-		createsSlices(waypoints);
-	}
-
-	/**
-	 * Creates the track slices.
-	 * 
-	 * @param wayPoints
-	 *            The way points of the track.
-	 */
-	private void createsSlices(List<WayPoint> wayPoints) {
-		if (wayPoints == null || getSliceSize() <= 0) {
-			return;
-		}
-
-		if (slices == null) {
-			slices = new ArrayList<IElevationProfile>();
-		} else {
-			slices.clear();
-		}
-
-		for (int i = 0; i < wayPoints.size(); i += getSliceSize()) {
-			int to = Math.min(i + getSliceSize(), wayPoints.size());
-			ElevationProfileLeaf ems = new ElevationProfileLeaf(getName(), this, wayPoints.subList(i, to));
-			slices.add(ems);
-		}
-		
-		// downsample
-		setWayPoints(WayPointHelper.downsampleWayPoints(wayPoints, getSliceSize()), false);
-	}
-
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#getChildren()
-	 */
-	@Override
-	public List<IElevationProfile> getChildren() {
-		return slices;
-	}
-}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationProfilePlugin.java	(revision 29907)
@@ -16,10 +16,14 @@
 
 import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
 import org.openstreetmap.josm.gui.IconToggleButton;
+import org.openstreetmap.josm.gui.MainMenu;
 import org.openstreetmap.josm.gui.MapFrame;
 import org.openstreetmap.josm.plugins.Plugin;
 import org.openstreetmap.josm.plugins.PluginInformation;
+import org.openstreetmap.josm.plugins.elevation.actions.AddElevationLayerAction;
 import org.openstreetmap.josm.plugins.elevation.gui.ElevationProfileDialog;
 import org.openstreetmap.josm.plugins.elevation.gui.ElevationProfileLayer;
+import static org.openstreetmap.josm.tools.I18n.tr;
 
 /**
@@ -44,10 +48,13 @@
 	    eleMode = new ElevationMapMode("Elevation profile", Main.map);
 	    eleModeButton = new IconToggleButton(eleMode);
+	    
+	    JosmAction action = new AddElevationLayerAction();
+	    
+	    MainMenu.add(Main.main.menu.viewMenu, action, false, 0);
+	    
 	} catch (Exception e1) {
 	    System.err.println("Init of ElevationProfilePlugin failed: " + e1);
 	    e1.printStackTrace();
 	}
-	
-	getPluginDir();
     }
 
@@ -77,5 +84,5 @@
     public static ElevationProfileLayer getCurrentLayer(){
 	if(currentLayer == null){
-	    currentLayer = new ElevationProfileLayer("Elevation profile");
+	    currentLayer = new ElevationProfileLayer(tr("Elevation Profile"));
 	    Main.main.addLayer(currentLayer);			
 	}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationRenderer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationRenderer.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationRenderer.java	(revision 29907)
@@ -0,0 +1,128 @@
+package org.openstreetmap.josm.plugins.elevation;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.Component;
+import java.io.IOException;
+import java.util.List;
+import java.util.concurrent.BlockingDeque;
+import java.util.concurrent.LinkedBlockingDeque;
+
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.gui.PleaseWaitRunnable;
+import org.openstreetmap.josm.gui.progress.NullProgressMonitor;
+import org.openstreetmap.josm.gui.progress.ProgressMonitor;
+import org.openstreetmap.josm.io.OsmTransferException;
+import org.xml.sax.SAXException;
+
+public class ElevationRenderer extends PleaseWaitRunnable {
+    private Bounds box;
+    private IEleRenderingListener listener;
+    
+    private BlockingDeque<EleVertex> toDo = new LinkedBlockingDeque<EleVertex>();
+    private BlockingDeque<EleVertex> vertices = new LinkedBlockingDeque<EleVertex>();
+    
+    private volatile boolean stop = false;
+    
+    public ElevationRenderer(String title, Bounds box, IEleRenderingListener listener) {
+	this(title, NullProgressMonitor.INSTANCE, true, box, listener);
+    }
+
+    public ElevationRenderer(String title, boolean ignoreException, Bounds box, IEleRenderingListener listener) {
+	this(title, NullProgressMonitor.INSTANCE, ignoreException, box, listener);
+    }
+
+    public ElevationRenderer(Component parent, String title,
+	    boolean ignoreException, Bounds box) throws IllegalArgumentException {
+	super(parent, title, ignoreException);
+	
+	this.box = box;
+	initQueue();
+    }
+
+    public ElevationRenderer(String title, ProgressMonitor progressMonitor,
+	    boolean ignoreException, Bounds box, IEleRenderingListener listener) {
+	super(title, progressMonitor, ignoreException);
+
+	this.box = box;
+	this.listener = listener;
+	initQueue();
+    }
+    
+    /**
+     * Inits the 'todo' queue with the initial vertices.
+     */
+    private void initQueue() {
+	LatLon min = box.getMin();
+	LatLon max = box.getMax();
+	
+	// compute missing coordinates
+	LatLon h1 = new LatLon(min.lat(), max.lon()); 
+	LatLon h2 = new LatLon(max.lat(), min.lon());
+	
+	// compute elevation coords
+	EleCoordinate p0 = new EleCoordinate(min, ElevationHelper.getElevation(min));	
+	EleCoordinate p1 = new EleCoordinate(h1, ElevationHelper.getElevation(h1));
+	EleCoordinate p2 = new EleCoordinate(max, ElevationHelper.getElevation(max));
+	EleCoordinate p3 = new EleCoordinate(h2, ElevationHelper.getElevation(h2));
+		
+	// compute initial vertices
+	EleVertex v1 = new EleVertex(p0, p1, p2);
+	EleVertex v2 = new EleVertex(p2, p3, p0);
+	// enqueue vertices
+	toDo.add(v1);
+	toDo.add(v2);
+	
+	System.out.println("Inited queue");
+    }
+
+    public BlockingDeque<EleVertex> getVertices() {
+        return vertices;
+    }
+
+    @Override
+    protected void cancel() {
+	stop = true;
+    }
+
+    @Override
+    protected void realRun() throws SAXException, IOException,
+	    OsmTransferException {
+	
+	if (stop) return;
+	
+	super.getProgressMonitor().indeterminateSubTask(tr("Render vertices..."));
+	System.out.println("Queue size " + toDo.size());
+	// 
+	while (toDo.size() > 0) {
+	    if (stop) break;
+	    
+	    EleVertex vertex = toDo.poll();
+	    
+	    if (vertex.isFinished()) {		
+		vertices.add(vertex);
+		if (listener !=null) {
+		    listener.finished(vertex);
+		}
+	    } else {
+		List<EleVertex> newV = vertex.divide();
+		for (EleVertex eleVertex : newV) {
+		    System.out.print(".");
+		    toDo.add(eleVertex);
+		}
+	    }
+	}
+	
+	if (listener !=null) {
+	    listener.finishedAll();
+	}
+    }
+
+    @Override
+    protected void finish() {
+	// TODO Auto-generated method stub
+
+    }
+
+}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationWayPointKind.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/ElevationWayPointKind.java	(revision 29906)
+++ 	(revision )
@@ -1,35 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-/**
- * @author Oliver Wieland <oliver.wieland@online.de>
- * Enumeration which classifies way points within an elevation profile.
- */
-public enum ElevationWayPointKind {
-	Plain, 				// Simple way point (equal to no or low slope)
-	Highlighted,			// Highlighted waypoint
-	StartPoint,			// First way point
-	EndPoint,			// Last way point
-	MaxElevation,			// Highest way point
-	MinElevation,			// Lowest way point 
-	ElevationGainHigh,		// Elevation gain (high slope 15-25%)
-	ElevationLossHigh,		// Elevation loss (high downward slope)
-	ElevationGainLow,		// Elevation gain (low slope, 5-14.9%)
-	ElevationLossLow,		// Elevation loss (low downward slope)
-	ElevationLevelGain,		// Elevation level gain (e. g. crossed 300m from lower elevation)
-	ElevationLevelLoss,		// Elevation level (e. g. crossed 300m from higher elevation)
-	FullHour			// Full Hour	
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/GeoidCorrectionKind.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/GeoidCorrectionKind.java	(revision 29906)
+++ 	(revision )
@@ -1,28 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-/**
- * @author Oliver Wieland <oliver.wieland@online.de>
- * Enumeration for available elevation correction modes. 
- */
-public enum GeoidCorrectionKind {
-	/** Elevation values remain unchanged */
-	None,
-	/** Automatic correction by geoid lookup table */
-	Auto,
-	/** Fixed value */
-	Fixed
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/GpxIterator.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/GpxIterator.java	(revision 29906)
+++ 	(revision )
@@ -1,140 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.Collection;
-
-import org.openstreetmap.josm.data.gpx.GpxData;
-import org.openstreetmap.josm.data.gpx.GpxRoute;
-import org.openstreetmap.josm.data.gpx.GpxTrack;
-import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Utility class to apply a visitor on GPX containers (track, route, data).
- * @author Oliver Wieland <oliver.wieland@online.de>
- */
-public class GpxIterator {
-	/**
-	 * Static class, no need to instantiate me.
-	 */
-	private GpxIterator() {}
-	
-	/**
-	 * Runs the given visitor on a GPX data instance. If one or both 
-	 * arguments are null, this method will return immediately. 
-	 * 
-	 * @param data
-	 *            The GPX data instance.
-	 * @param visitor
-	 *            The visitor which inspects all GPX entities.
-	 */
-	public static void visit(GpxData data, IGpxVisitor visitor) {
-		if (data == null) return;
-		if (visitor == null) return;
-		
-		visitor.start();
-		visitSingleWaypoints(data, visitor);
-		visitor.end();
-
-		// routes
-		if (data.hasRoutePoints()) {
-			for (GpxRoute rte : data.routes) {
-				visitRoute(visitor, rte);
-			}
-		}
-
-		// tracks
-		for (GpxTrack trk : data.tracks) {
-			visitTrack(visitor, trk);
-		}
-	}
-	
-	/**
-	 * Visits a single GPX track. 
-	 * @param track The track to visit.
-	 * @param visitor
-	 *            The visitor which inspects all GPX entities.
-	 */
-	public static void visit(GpxTrack track, IGpxVisitor visitor) {
-		visitTrack(visitor, track);
-	}
-	
-	/**
-	 * Visits a single GPX route. 
-	 * @param route The route to visit.
-	 * @param visitor
-	 *            The visitor which inspects all GPX entities.
-	 */
-	public static void visit(GpxRoute route, IGpxVisitor visitor) {
-		visitRoute(visitor, route);
-	}
-
-	// ---------------------- Helper methods ----------------
-	
-	/**
-	 * @param visitor
-	 * @param trk
-	 */
-	private static void visitTrack(IGpxVisitor visitor, GpxTrack trk) {
-		if (trk == null) return;
-		if (visitor == null) return;
-		
-		Collection<GpxTrackSegment> segments = trk.getSegments();
-		visitor.start();
-
-		if (segments != null) {
-			for (GpxTrackSegment segment : segments) {
-				Collection<WayPoint> waypts = segment.getWayPoints();
-				// no visitor here...
-				if (waypts == null)
-					continue;
-
-				for (WayPoint wayPoint : waypts) {
-					visitor.visit(wayPoint);
-				}
-			}
-		}
-		visitor.end();
-	}
-
-	/**
-	 * @param visitor
-	 * @param route
-	 */
-	private static void visitRoute(IGpxVisitor visitor, GpxRoute route) {
-		if (route == null) return;
-		if (visitor == null) return;
-		
-		visitor.start();
-		for (WayPoint wpt : route.routePoints) {
-			visitor.visit(wpt);
-		}
-		visitor.end();
-	}
-
-	/**
-	 * @param data
-	 * @param visitor
-	 */
-	private static void visitSingleWaypoints(GpxData data, IGpxVisitor visitor) {
-		// isolated way points
-		if (data.waypoints != null) { // better with an hasWaypoints method!?
-			for (WayPoint wpt : data.waypoints) {
-				visitor.visit(wpt);
-			}
-		}
-	}
-}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/HgtReader.java	(revision 29907)
@@ -48,6 +48,7 @@
     	    		File f = new File(fullPath);
     	    		if (f.exists()) {
-    	    		    // nope: read HGT file...
+    	    		    // found something: read HGT file...
     	    		    ShortBuffer data = readHgtFile(fullPath);
+    	    		    System.out.println("Read SRTM data from " + fullPath + ", tag is '" + file + "'");
     	    		    // ... and store result in cache
     	    		    cache.put(file, data);
@@ -55,16 +56,19 @@
     	    		}
 	        }
-	    }
+	    } 
+	    
+	    System.out.println("Get elevation from HGT file " + file);
 	    
 	    // read elevation value
 	    return readElevation(coor);
 	} catch (FileNotFoundException e) {
+	    System.err.println("Get elevation from HGT " + coor + " failed: => " + e.getMessage());
 	    // no problem... file not there
-	    return Double.NaN;
+	    return ElevationHelper.NO_ELEVATION;
 	} catch (Exception ioe) {
 	    // oops...
-	    ioe.printStackTrace();	    
+	    ioe.printStackTrace(System.err);	    
 	    // fallback
-	    return Double.NaN;	    
+	    return ElevationHelper.NO_ELEVATION;	    
 	} 
     }
@@ -107,5 +111,6 @@
 	
 	if (sb == null) {
-	    return Double.NaN;
+	    System.out.println("readElevation: Buffer is null for tag '" + tag + "'");
+	    return ElevationHelper.NO_ELEVATION;
 	}
 	
@@ -120,16 +125,19 @@
 	row = HGT_ROW_LENGTH - row;
 	int cell = (HGT_ROW_LENGTH*  (row - 1)) + col;
+	
+	//System.out.println("Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + ", " + sb.limit());
 
 	// valid position in buffer?
 	if (cell < sb.limit()) {
 	    short ele = sb.get(cell);
+	    //System.out.println("==> Read SRTM elevation data from row/col/cell " + row + "," + col + ", " + cell + " = " + ele);
 	    // check for data voids 
 	    if (ele == HGT_VOID) {
-		return Double.NaN;
+		return ElevationHelper.NO_ELEVATION;
 	    } else {
 		return ele;
 	    }
 	} else {
-	    return Double.NaN;
+	    return ElevationHelper.NO_ELEVATION;
 	}
     }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IEleRenderingListener.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IEleRenderingListener.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IEleRenderingListener.java	(revision 29907)
@@ -0,0 +1,16 @@
+package org.openstreetmap.josm.plugins.elevation;
+
+public interface IEleRenderingListener {
+    
+    /**
+     * Notifies client that an elevation vertex has been finished for rendering.
+     *
+     * @param vertex the vertex
+     */
+    public void finished(EleVertex vertex);
+    
+    /**
+     * Notifies a client that all vertices can be rendered now.
+     */
+    public void finishedAll();
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationModelListener.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationModelListener.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IElevationModelListener.java	(revision 29907)
@@ -15,4 +15,6 @@
 package org.openstreetmap.josm.plugins.elevation;
 
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationModel;
+
 /**
  * This interface is intended to allow clients reaction on changes in the elevation model changes (e. g. 
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IGpxVisitor.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IGpxVisitor.java	(revision 29906)
+++ 	(revision )
@@ -1,40 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Interface for all GPX visitors.
- * @author Oliver Wieland <oliver.wieland@online.de>
- */
-public interface IGpxVisitor extends IGpxWaypointVisitor {
-	/**
-	 * Starts a GPX route, track or way point collection.
-	 */
-	void start();
-	
-	/**
-	 * Ends a GPX route, track or way point collection.
-	 */
-	void end();
-	
-	/**
-	 * Visits a way point within a GPX route.
-	 * @param route The route containing the way point.
-	 * @param wp The way point to visit.
-	 */
-	void visit(WayPoint wp);
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IGpxWaypointVisitor.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/IGpxWaypointVisitor.java	(revision 29906)
+++ 	(revision )
@@ -1,30 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * @author Oliver Wieland <oliver.wieland@online.de>
- * Interface for all GPX data visitors. Hopefully this will be part of JOSM some day.
- */
-public interface IGpxWaypointVisitor {
-	/**
-	 * Visits a way point. This method is called for isolated way points, i. e. way points
-	 * without an associated route or track. 
-	 * @param wp The way point to visit.
-	 */
-	void visit(WayPoint wp);
-}
Index: plications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/WayPointHelper.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/WayPointHelper.java	(revision 29906)
+++ 	(revision )
@@ -1,332 +1,0 @@
-/**
- * This program is free software: you can redistribute it and/or modify it under 
- * the terms of the GNU General Public License as published by the 
- * Free Software Foundation, either version 3 of the License, or 
- * (at your option) any later version. 
- * 
- * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
- * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
- * See the GNU General Public License for more details. 
- * 
- * You should have received a copy of the GNU General Public License along with this program. 
- * If not, see <http://www.gnu.org/licenses/>.
- */
-
-package org.openstreetmap.josm.plugins.elevation;
-
-import java.util.ArrayList;
-import java.util.Calendar;
-import java.util.GregorianCalendar;
-import java.util.List;
-import java.util.Locale;
-
-import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-
-/**
- * Provides methods to access way point attributes and some utility methods regarding elevation stuff (
- * e. g. special text formats, unit conversion, geoid calc).
- * @author Oliver Wieland <oliver.wieland@online.de> 
- */
-public class WayPointHelper {
-	public static double METER_TO_FEET = 3.280948;
-	
-	/* Countries which use the imperial system instead of the metric system. */
-	private static String IMPERIAL_SYSTEM_COUNTRIES[] = {
-		"en_US", 	/* USA */
-		"en_CA",	/* Canada */
-		"en_AU",	/* Australia */
-		"en_NZ",	/* New Zealand */
-//		"de_DE",	/* for testing only */
-		"en_ZA"	/* South Africa */
-	};
-	
-	
-	
-	/**
-	 * The name of the elevation height of a way point.
-	 */
-	public static final String HEIGHT_ATTRIBUTE = "ele";
-	
-	private static UnitMode unitMode = UnitMode.NotSelected;
-		
-	private static GeoidCorrectionKind geoidKind = GeoidCorrectionKind.None;
-	
-	/** The HGT reader instance. */
-	private static HgtReader hgt = new HgtReader();
-	
-	/**
-	 * Gets the current mode of GEOID correction.
-	 * @return
-	 */
-	public static GeoidCorrectionKind getGeoidKind() {
-		return geoidKind;
-	}
-
-	public static void setGeoidKind(GeoidCorrectionKind geoidKind) {
-		WayPointHelper.geoidKind = geoidKind;
-	}
-	
-	/**
-	 * Gets the current unit mode (metric or imperial).
-	 * @return
-	 */
-	public static UnitMode getUnitMode() {
-		//TODO: Use this until /JOSM/src/org/openstreetmap/josm/gui/NavigatableComponent.java 
-		// has a an appropriate method 
-		
-		// unit mode already determined?
-		if (unitMode != UnitMode.NotSelected) {
-			return unitMode;
-		}
-		
-		// Set default
-		unitMode = UnitMode.Metric;
-		
-		// Check if user could prefer imperial system 
-		Locale l = Locale.getDefault();		
-		for (int i = 0; i < IMPERIAL_SYSTEM_COUNTRIES.length; i++) {
-			String ctry = l.toString();
-			if (IMPERIAL_SYSTEM_COUNTRIES[i].equals(ctry)) {
-				unitMode = UnitMode.Imperial;
-			}
-		}
-		
-		return unitMode;
-	}
-	
-	/**
-	 * Gets the unit string for elevation ("m" or "ft").
-	 * @return
-	 */
-	public static String getUnit() {		
-		switch (getUnitMode()) {
-		case Metric:
-			return "m";
-		case Imperial:
-			return "ft";
-		default:
-			throw new RuntimeException("Invalid or unsupported unit mode: " + unitMode);
-		}
-	}
-	
-	/**
-	 * Gets the elevation (Z coordinate) of a GPX way point in meter or feet (for
-	 * US, UK, ZA, AU, NZ and CA). 
-	 * 
-	 * @param wpt
-	 *            The way point instance.
-	 * @return The x coordinate or 0, if the given way point is null or contains
-	 *         not height attribute.
-	 */
-	public static double getElevation(WayPoint wpt) {
-		double ele = getInternalElevation(wpt);
-
-		if (getUnitMode() == UnitMode.Imperial) {
-				// translate to feet
-		    return meter2Feet(ele);
-		}	
-		
-		return ele;
-	}
-	
-	/**
-	 * Computes the slope <b>in percent</b> between two way points. E. g. an elevation gain of 12m 
-	 * within a distance of 100m is equal to a slope of 12%. 
-	 *
-	 * @param w1 the first way point
-	 * @param w2 the second way point
-	 * @return the slope in percent
-	 */
-	public static double computeSlope(WayPoint w1, WayPoint w2) {
-	    	// same coordinates? -> return 0, if yes
-	    	if (w1.getCoor().equals(w2.getCoor())) return 0;
-	    
-		// get distance in meters and divide it by 100 in advance
-		double distInMeter = w1.getCoor().greatCircleDistance(w2.getCoor()) / 100.0;
-		
-		// convert to feet?
-		if (getUnitMode() == UnitMode.Imperial) {
-		    distInMeter = meter2Feet(distInMeter);
-		}
-				
-		// get elevation (difference) - is converted automatically to feet
-		int ele1 = (int) WayPointHelper.getElevation(w1);
-		int ele2 = (int) WayPointHelper.getElevation(w2);
-		int dH = ele2 - ele1;
-		
-		// Slope in percent is define as elevation gain/loss in meters related to a distance of 100m
-		return dH / distInMeter;
-	}
-	
-	/**
-	 * Converts meter into feet
-	 *
-	 * @param meter the meter
-	 * @return the double
-	 */
-	public static double meter2Feet(double meter) {
-	    return meter * METER_TO_FEET;
-	}
-	
-	/**
-	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
-	 * @param elevation
-	 * @return
-	 */
-	public static String getElevationText(int elevation) {
-		return String.format("%d %s", elevation, getUnit());
-	}
-	
-	/**
-	 * Gets the elevation string for a given elevation, e. g "300m" or "800ft".
-	 * @param elevation
-	 * @return
-	 */
-	public static String getElevationText(double elevation) {
-		return String.format("%d %s", (int)Math.round(elevation), getUnit());
-	}
-	
-	/**
-	 * Gets the elevation string for a given way point, e. g "300m" or "800ft".
-	 * @param elevation
-	 * @return
-	 */
-	public static String getElevationText(WayPoint wpt) {
-		if (wpt == null) return null;
-		
-		int elevation = (int)Math.round(WayPointHelper.getElevation(wpt));
-		return String.format("%d %s", (int)elevation, getUnit());
-	}
-	
-	/**
-	 * Get the time string for a given way point.
-	 * @param wpt
-	 * @return
-	 */
-	public static String getTimeText(WayPoint wpt) {
-		if (wpt == null) return null; 
-		
-		int hour = WayPointHelper.getHourOfWayPoint(wpt);
-		int min = WayPointHelper.getMinuteOfWayPoint(wpt);		
-		return String.format("%02d:%02d", hour, min);
-	}
-
-	/**
-	 * Gets the elevation (Z coordinate) of a GPX way point.
-	 * 
-	 * @param wpt
-	 *            The way point instance.
-	 * @return The x coordinate or 0, if the given way point is null or contains
-	 *         not height attribute.
-	 */
-	private static double getInternalElevation(WayPoint wpt) {
-		if (wpt != null) {
-		    	// Try to read data from SRTM file
-		    	// TODO: Option to switch this off
-		    	double eleHgt = hgt.getElevationFromHgt(wpt.getCoor());
-		    	
-		    	if (!Double.isNaN(eleHgt)) {		    	    
-		    	    return eleHgt;
-		    	}
-		    
-			if (!wpt.attr.containsKey(HEIGHT_ATTRIBUTE)) {
-				return 0;
-			}
-
-			String height = wpt.getString(WayPointHelper.HEIGHT_ATTRIBUTE);
-			try {
-				double z = Double.parseDouble(height);
-
-				if (geoidKind == GeoidCorrectionKind.Auto) {
-					byte h = getGeoidCorrection(wpt);
-					z += h;
-				}
-				return z;
-			} catch (NumberFormatException e) {
-				System.err.println(String.format(
-						"Cannot parse double from '%s': %s", height, e
-								.getMessage()));
-				return 0;
-			}
-		} else {
-			return 0;
-		}
-	}
-
-	/*
-	 * Gets the geoid height for the given way point. See also {@link
-	 * GeoidData}.
-	 */
-	public static byte getGeoidCorrection(WayPoint wpt) {
-	    	/*
-		int lat = (int)Math.round(wpt.getCoor().lat());
-		int lon = (int)Math.round(wpt.getCoor().lon());
-		byte geoid = GeoidData.getGeoid(lat, lon);
-		
-		System.out.println(
-				String.format("Geoid(%d, %d) = %d", lat, lon, geoid));
-	    	 */
-		return 0;
-	}
-
-	/**
-	 * Reduces a given list of way points to the specified target size.
-	 * 
-	 * @param origList
-	 *            The original list containing the way points.
-	 * @param targetSize
-	 *            The desired target size of the list. The resulting list may
-	 *            contain fewer items, so targetSize should be considered as
-	 *            maximum.
-	 * @return A list containing the reduced list.
-	 */
-	public static List<WayPoint> downsampleWayPoints(List<WayPoint> origList,
-			int targetSize) {
-		if (origList == null)
-			return null;
-		if (targetSize <= 0)
-			throw new IllegalArgumentException(
-					"targetSize must be greater than zero");
-
-		int origSize = origList.size();
-		if (origSize <= targetSize) {
-			return origList;
-		}
-
-		int delta = (int) Math.max(Math.ceil(origSize / targetSize), 2);
-
-		List<WayPoint> res = new ArrayList<WayPoint>(targetSize);
-		for (int i = 0; i < origSize; i += delta) {
-			res.add(origList.get(i));
-		}
-
-		return res;
-	}
-	
-	/**
-	 * Gets the hour value of a way point in 24h format.
-	 * @param wpt
-	 * @return
-	 */
-	public static int getHourOfWayPoint(WayPoint wpt) {
-		if (wpt == null) return -1;
-		
-		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-		calendar.setTime(wpt.getTime());   // assigns calendar to given date 
-		return calendar.get(Calendar.HOUR_OF_DAY); 
-	}
-	
-	/**
-	 * Gets the minute value of a way point in 24h format.
-	 * @param wpt
-	 * @return
-	 */
-	public static int getMinuteOfWayPoint(WayPoint wpt) {
-		if (wpt == null) return -1;
-		
-		Calendar calendar = GregorianCalendar.getInstance(); // creates a new calendar instance
-		calendar.setTime(wpt.getTime());   // assigns calendar to given date 
-		return calendar.get(Calendar.MINUTE); 
-	}
-}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/actions/AddElevationLayerAction.java	(revision 29907)
@@ -0,0 +1,32 @@
+package org.openstreetmap.josm.plugins.elevation.actions;
+
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.actions.JosmAction;
+import org.openstreetmap.josm.plugins.elevation.ColoredElevationLayer;
+
+public class AddElevationLayerAction extends JosmAction {
+
+    /**
+     * 
+     */
+    private static final long serialVersionUID = -745642875640041385L;
+    private ColoredElevationLayer currentLayer;
+
+    public AddElevationLayerAction() {
+	super(tr("Elevation Map Layer"), "elevation", tr("Shows elevation layer"), null, true);
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+	if (currentLayer == null) {
+	    currentLayer = new ColoredElevationLayer(tr("Elevation Map")); // TODO: Better name
+	    Main.main.addLayer(currentLayer);
+	}
+
+    }
+
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java	(revision 29907)
@@ -0,0 +1,242 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxRoute;
+import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.IElevationModelListener;
+import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+
+/**
+ * Represents the top-level part of the elevation model. The elevation model
+ * breaks done into the tracks/routes of a GPX file (see
+ * {@link ElevationProfileNode}). Each track is divided into 'slices' (see
+ * {@link ElevationProfileLeaf}) - a set of fixed number of way points. This
+ * structure allows as well an overview over a single track as a detailed
+ * elevation view of a track part.
+ * 
+ * @see ElevationProfileNode
+ * @see ElevationProfileLeaf
+ * @see IElevationModelTrackListener
+ * @see IElevationModelSliceListener
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ */
+public class ElevationModel extends ElevationProfileBase implements IGpxVisitor {
+	// private int sliceSize;
+	private int trackCounter;
+	private GpxData gpxData;
+
+	private List<IElevationProfile> tracks;
+	private List<WayPoint> buffer = new ArrayList<WayPoint>(1000);
+	private List<WayPoint> tmpWaypoints = new ArrayList<WayPoint>(1000);
+
+	private List<IElevationModelListener> listeners = new ArrayList<IElevationModelListener>();
+
+	public ElevationModel() {
+		this("", null, 100);
+	}
+
+	public ElevationModel(String name, GpxData data, int sliceSize) {
+		super(name);
+		gpxData = data;
+		setSliceSize(Math.max(sliceSize, 100));
+	}
+
+	@Override
+	public void setSliceSize(int sliceSize) {
+
+		super.setSliceSize(sliceSize);
+
+		// FIXME: Listener should go in base class
+		updateElevationData();
+		fireModelChanged();
+	}
+
+	/**
+	 * Gets the GPX data instance used by this model.
+	 * 
+	 * @return
+	 */
+	public GpxData getGpxData() {
+		return gpxData;
+	}
+	
+	/**
+	 * @return the tracks
+	 */
+	protected List<IElevationProfile> getTracks() {
+		return tracks;
+	}
+
+	/**
+	 * Gets a flag indicating whether the associated way points contained
+	 * elevation data or not. This is the case if min and max height or both
+	 * zero.
+	 * 
+	 * @return
+	 */
+	public boolean hasElevationData() {
+		return getMaxHeight() != getMinHeight();
+	}
+
+	/**
+	 * Fires the 'model changed' event to all listeners.
+	 */
+	protected void fireModelChanged() {
+		for (IElevationModelListener listener : listeners) {
+			listener.elevationProfileChanged(this);
+		}
+	}
+
+	/**
+	 * Adds a model listener to this instance.
+	 * 
+	 * @param listener
+	 *            The listener to add.
+	 */
+	public void addModelListener(IElevationModelListener listener) {
+		this.listeners.add(listener);
+	}
+
+	/**
+	 * Removes a model listener from this instance.
+	 * 
+	 * @param listener
+	 *            The listener to remove.
+	 */
+	public void removeModelListener(IElevationModelListener listener) {
+		this.listeners.remove(listener);
+	}
+
+	/**
+	 * Removes all listeners from this instance.
+	 */
+	public void removeAllListeners() {
+		this.listeners.clear();
+	}
+
+	/**
+	 * (Re)computes the elevation model.
+	 */
+	private void computeProfile() {
+		if (gpxData == null)
+			return; // nothing to do
+
+		trackCounter = 0;
+
+		super.updateValues();
+		if (tracks == null) {
+			tracks = new ArrayList<IElevationProfile>();
+		} else {
+			tmpWaypoints.clear();
+			buffer.clear();
+			tracks.clear();
+		}
+
+		setDistance(gpxData.length());	// get distance from GPX 
+		GpxIterator.visit(gpxData, this);
+
+		// reduce data
+		setWayPoints(ElevationHelper.downsampleWayPoints(tmpWaypoints,
+				getSliceSize()), false);
+	}
+
+	/**
+	 * Forces the model to refresh itself. Clients (e. g. UI widgets) may use
+	 * this method to notify the model on UI changes.
+	 */
+	public void updateElevationData() {
+		computeProfile();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IGpxVisitor#visit(org.openstreetmap
+	 * .josm.data.gpx.GpxRoute, org.openstreetmap.josm.data.gpx.WayPoint)
+	 */
+	public void visit(GpxRoute route, WayPoint wp) {
+		processWayPoint(wp);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IGpxVisitor#visit(org.openstreetmap
+	 * .josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment,
+	 * org.openstreetmap.josm.data.gpx.WayPoint)
+	 */
+	public void visit(GpxTrack track, GpxTrackSegment segment, WayPoint wp) {
+		processWayPoint(wp);
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#visit(org.openstreetmap.josm.data.gpx.WayPoint)
+	 */
+	@Override
+	public void visit(WayPoint wp) {
+		super.visit(wp);
+		processWayPoint(wp);
+	}
+
+	public void start() {
+		buffer.clear();
+	}
+
+	public void end() {
+		String trackName = "Track#" + trackCounter;
+		addTrackOrRoute(trackName);		
+	}
+	
+	private void addTrackOrRoute(String trackName) {
+		if (getSliceSize() > 0) {
+			ElevationProfileNode emt = new ElevationProfileNode(trackName,
+					this, buffer, getSliceSize());
+			tracks.add(emt);
+		}
+		trackCounter++;
+		buffer.clear();
+	}
+
+	private void processWayPoint(WayPoint wp) {
+		if (wp == null) {
+			throw new RuntimeException("WPT must not be null!");
+		}
+		
+		buffer.add(wp);
+		tmpWaypoints.add(wp);
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#getChildren
+	 * ()
+	 */
+	@Override
+	public List<IElevationProfile> getChildren() {
+		return tracks;
+	}
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileBase.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileBase.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileBase.java	(revision 29907)
@@ -0,0 +1,518 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import java.util.ArrayList;
+import java.util.Date;
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+
+/**
+ * Base class for an elevation profile. An elevation profile is constructed out
+ * of a set of way points. The profile computes min/max/average height from the
+ * full way point set and then reduces the number of way points to a given
+ * amount, if necessary.
+ * 
+ * The computation is done via implementing {@link IGpxWaypointVisitor},
+ * subclasses may override the {@link ElevationProfileBase#visit(WayPoint)}
+ * method to compute own values or run specific actions. The computation is
+ * triggered by calling {@link ElevationProfileBase#updateValues()}.
+ * 
+ * Elevation profiles can break down into further child profiles. This is
+ * intended to show different levels of details, if the number of way points
+ * exceed the display space (which is usually the case).
+ * 
+ * {@link IElevationProfile} {@link IGpxWaypointVisitor} {@link GpxIterator}
+ * 
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * 
+ */
+public abstract class ElevationProfileBase implements IElevationProfile,
+		IGpxWaypointVisitor {
+	public static final int WAYPOINT_START = 0;
+	public static final int WAYPOINT_END = 1;
+	public static final int WAYPOINT_MIN = 2;
+	public static final int WAYPOINT_MAX = 3;
+
+	private String name;
+	private int minHeight;
+	private int maxHeight;
+	private int avrgHeight;
+	private double dist;
+	private Date start = new Date();
+	private Date end = new Date();
+	private WayPoint[] importantWayPoints = new WayPoint[4];
+	private IElevationProfile parent;
+	private int sumEle; // temp var for average height
+	private List<WayPoint> wayPoints;
+	private int numWayPoints; // cached value
+	private int sliceSize;
+	private int gain;
+	private int lastEle;
+	private static boolean ignoreZeroHeight = true;
+
+	/**
+	 * Creates a name elevation profile without any way points.
+	 * 
+	 * @param name
+	 */
+	public ElevationProfileBase(String name) {
+		this(name, null, null, 0);
+	}
+
+	/**
+	 * Creates a name elevation profile with a given set of way points.
+	 * 
+	 * @param name
+	 *            The name of the profile.
+	 * @param parent
+	 *            The (optional) parent profile.
+	 * @param wayPoints
+	 *            The list containing the way points of the profile.
+	 * @param sliceSize
+	 *            The requested target size of the profile.
+	 */
+	public ElevationProfileBase(String name, IElevationProfile parent,
+			List<WayPoint> wayPoints, int sliceSize) {
+		super();
+		this.name = name;
+		this.parent = parent;
+		this.sliceSize = sliceSize;
+		setWayPoints(wayPoints, true);
+	}
+
+	public static boolean isIgnoreZeroHeight() {
+		return ignoreZeroHeight;
+	}
+
+	public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) {
+		ElevationProfileBase.ignoreZeroHeight = ignoreZeroHeight;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#invalidateModel
+	 * (int)
+	 */
+	public void updateElevationData() {
+		updateValues();
+	}
+
+	/**
+	 * Revisits all way points and recomputes the characteristic values like
+	 * min/max elevation.
+	 */
+	protected void updateValues() {
+		if (wayPoints == null)
+			return;
+		
+		int n = this.wayPoints.size(); 
+		if (n == 0)
+			return;
+
+		start = new Date();		
+		end = new Date(0L);
+		this.minHeight = Integer.MAX_VALUE;
+		this.maxHeight = Integer.MIN_VALUE;
+		sumEle = 0;
+		gain = 0;
+		lastEle = 0;
+		
+		for (WayPoint wayPoint : this.wayPoints) {
+			visit(wayPoint);
+		}
+		
+		if (this.minHeight == Integer.MAX_VALUE && this.maxHeight == Integer.MIN_VALUE) {
+			// file does not contain elevation data	at all
+			minHeight = 0;
+			maxHeight = 0;
+			setMinWayPoint(wayPoints.get(0));
+			setMaxWayPoint(wayPoints.get(n-1));
+		}		
+		
+		//if (start.after(end) || start.equals(end)) {
+			// GPX does not contain time stamps -> use sequential order
+			setStart(wayPoints.get(0));
+			setEnd(wayPoints.get(n-1));
+		//}
+		
+		avrgHeight = sumEle / n;
+	}
+
+	/**
+	 * Gets the name of the profile. 
+	 */
+	public String getName() {
+		return name;
+	}
+
+	/**
+	 * Sets the name of the profile.
+	 * @param name The new name of the profile.
+	 */
+	public void setName(String name) {
+		this.name = name;
+	}
+
+	/**
+	 * Sets the way point with the lowest elevation.
+	 * @param wp The way point instance having the lowest elevation.
+	 */
+	protected void setMinWayPoint(WayPoint wp) {
+		importantWayPoints[WAYPOINT_MIN] = wp;
+		this.minHeight = (int) ElevationHelper.getElevation(wp);
+	}
+
+	/**
+	 * Sets the way point with the highest elevation.
+	 * @param wp The way point instance having the highest elevation.
+	 */
+	protected void setMaxWayPoint(WayPoint wp) {
+		importantWayPoints[WAYPOINT_MAX] = wp;
+		this.maxHeight = (int) ElevationHelper.getElevation(wp);
+	}
+
+	/**
+	 * Sets the average height.
+	 * @param avrgHeight
+	 */
+	protected void setAvrgHeight(int avrgHeight) {
+		this.avrgHeight = avrgHeight;
+	}
+
+	/**
+	 * Sets the very first way point. 
+	 * @param wp
+	 */
+	protected void setStart(WayPoint wp) {
+		importantWayPoints[WAYPOINT_START] = wp;
+		this.start = wp.getTime();
+	}
+
+	/**
+	 * Sets the very last way point.
+	 * @param wp
+	 */
+	protected void setEnd(WayPoint wp) {
+		importantWayPoints[WAYPOINT_END] = wp;
+		this.end = wp.getTime();
+	}
+
+	public void setParent(IElevationProfile parent) {
+		this.parent = parent;
+	}
+
+	/**
+	 * Sets the way points of this profile.
+	 * 
+	 * @param wayPoints
+	 */
+	public void setWayPoints(List<WayPoint> wayPoints, boolean revisit) {
+		if (this.wayPoints != wayPoints) {
+			this.wayPoints = new ArrayList<WayPoint>(wayPoints);
+			numWayPoints = wayPoints != null ? wayPoints.size() : 0;
+			if (revisit) {				
+				updateValues();
+			}
+		}
+	}
+
+	/**
+	 * Checks if the given index is valid or not.
+	 * 
+	 * @param index
+	 *            The index to check.
+	 * @return true, if the given index is valid; otherwise false.
+	 */
+	protected boolean checkIndex(int index) {
+		return index >= 0 && index < getNumberOfWayPoints();
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#elevationValueAt
+	 * (int)
+	 */
+	public int elevationValueAt(int i) {
+		if (checkIndex(i)) {
+			return (int) ElevationHelper.getElevation(wayPoints.get(i));
+		} else {
+			throw new IndexOutOfBoundsException(String.format(
+					"Invalid index: %d, expected 0..%d", i,
+					getNumberOfWayPoints()));
+		}
+	}
+
+	/**
+	 * Gets the slice size for the detail view.
+	 * 
+	 * @return
+	 */
+	public int getSliceSize() {
+		return sliceSize;
+	}
+
+	/**
+	 * Sets the desired size of the elevation profile.
+	 */
+	public void setSliceSize(int sliceSize) {
+		if (this.sliceSize != sliceSize) {
+			this.sliceSize = sliceSize;
+		}
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getAverageHeight
+	 * ()
+	 */
+	public int getAverageHeight() {
+		return avrgHeight;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getChildren()
+	 */
+	public abstract List<IElevationProfile> getChildren();
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEnd()
+	 */
+	public Date getEnd() {
+		return end;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxHeight()
+	 */
+	public int getMaxHeight() {
+		return maxHeight;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinHeight()
+	 */
+	public int getMinHeight() {
+		return minHeight;
+	}
+
+	/**
+	 * Gets the difference between min and max elevation.
+	 * 
+	 * @return
+	 */
+	public int getHeightDifference() {
+		return maxHeight - minHeight;		
+	}
+	
+	/**
+	 * Gets the elevation gain.
+	 * 
+	 * @return
+	 */
+	public int getGain() {
+		return gain;
+	}
+	
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getDistance()
+	 */
+	@Override
+	public double getDistance() {
+		return dist; // dist is in meters
+	}
+	
+	/**
+	 * Sets the distance of the elevation profile.
+	 * @param dist
+	 */
+	protected void setDistance(double dist) {
+		this.dist = dist; 
+	}
+
+	/**
+	 * Returns the time between start and end of the track.
+	 * @return
+	 */
+	public long getTimeDifference() {
+		WayPoint wp1 = getStartWayPoint();
+		WayPoint wp2 = getEndWayPoint();
+		
+		if (wp1 != null && wp2 != null) {
+			long diff = wp2.getTime().getTime() - wp1.getTime().getTime();
+			return diff;
+		}
+		
+		return 0L;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getParent()
+	 */
+	public IElevationProfile getParent() {
+		return parent;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStart()
+	 */
+
+	public Date getStart() {
+		return start;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getEndWayPoint
+	 * ()
+	 */
+
+	public WayPoint getEndWayPoint() {
+		return importantWayPoints[WAYPOINT_END];
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMaxWayPoint
+	 * ()
+	 */
+
+	public WayPoint getMaxWayPoint() {
+		return importantWayPoints[WAYPOINT_MAX];
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getMinWayPoint
+	 * ()
+	 */
+
+	public WayPoint getMinWayPoint() {
+		return importantWayPoints[WAYPOINT_MIN];
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getStartWayPoint
+	 * ()
+	 */
+	public WayPoint getStartWayPoint() {
+		return importantWayPoints[WAYPOINT_START];
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @see
+	 * org.openstreetmap.josm.plugins.elevation.IElevationProfile#getWayPoints()
+	 */
+	public List<WayPoint> getWayPoints() {
+		return wayPoints;
+	}
+
+	/*
+	 * (non-Javadoc)
+	 * 
+	 * @seeorg.openstreetmap.josm.plugins.elevation.ElevationProfileBase#
+	 * getNumberOfWayPoints()
+	 */
+	public int getNumberOfWayPoints() {
+		return numWayPoints;// wayPoints != null ? wayPoints.size() : 0;
+	}
+
+	/**
+	 * Gets a flag indicating whether the associated way points contained
+	 * elevation data or not. This is the case if min and max height or both
+	 * zero.
+	 * 
+	 * @return
+	 */
+	public boolean hasElevationData() {
+		return minHeight != maxHeight;
+	}
+
+	/**
+	 * Visits a way point in order to update statistical values about the given
+	 * way point list.
+	 */
+	public void visit(WayPoint wp) {
+		if (wp.getTime().after(end)) {
+			setEnd(wp);
+		}
+
+		if (wp.getTime().before(start)) {
+			setStart(wp);
+		}
+
+		int ele = (int) ElevationHelper.getElevation(wp);
+
+		if (!isIgnoreZeroHeight() || ele > 0) {
+			if (ele > maxHeight) {
+				setMaxWayPoint(wp);
+			}
+			if (ele < minHeight) {
+				setMinWayPoint(wp);
+			}
+			
+			if (ele > lastEle) {
+				gain += ele - lastEle;
+			}
+
+			sumEle += ele;
+			lastEle = ele;			
+		}
+	}
+	
+	public String toString() {
+		return "ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
+				+ ", minHeight=" + getMinHeight() + ", maxHeight="
+				+ getMaxHeight() + "]";
+	}
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileLeaf.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileLeaf.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileLeaf.java	(revision 29907)
@@ -0,0 +1,64 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+
+/**
+ * This class represents a 'leaf node' in the elevation profile tree. It has no children and ignores
+ * the slice size parameter. So no data reduction takes places; every way point is kept.   
+ * 
+ * ElevationModelSlice is intended to be used internally.
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ *
+ */
+public class ElevationProfileLeaf extends ElevationProfileBase {
+	/**
+	 * Creates a name elevation profile leaf with a given set of way points.
+	 * @param name The name of the profile.
+	 * @param parent The (optional) parent profile.
+	 * @param wayPoints The list containing the way points of the profile.
+	 */
+	public ElevationProfileLeaf(String name, IElevationProfile parent, List<WayPoint> wayPoints) {
+		super(name, parent, wayPoints, 0);		
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#elevationValueAt(int)
+	 */
+	@Override
+	public int elevationValueAt(int i) {
+		if (i < 0 || i >= getNumberOfWayPoints()) throw new IndexOutOfBoundsException("Wrong index: " + i);
+		return (int)ElevationHelper.getElevation(getWayPoints().get(i));
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationProfile#getChildren()
+	 */
+	@Override
+	public List<IElevationProfile> getChildren() {
+		return null; // we have no children
+	}
+	
+	@Override
+	public String toString() {
+		return "ElevationModelSlice [avrgEle=" + getAverageHeight() + ", maxEle=" + getMaxHeight()
+				+ ", minEle=" + getMinHeight() + ", name=" + getName() + ", wayPoints="
+				+ getNumberOfWayPoints() + "]";
+	}
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileNode.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileNode.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfileNode.java	(revision 29907)
@@ -0,0 +1,126 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import java.util.ArrayList;
+import java.util.List;
+
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+
+/**
+ * Represents a elevation model of a single GPX track, route or collection of
+ * way points. It usually breaks down into many slices represented by 
+ * {@link ElevationProfileLeaf} which are accessible via {@link ElevationProfileBase#getChildren()}.
+ * 
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * 
+ * @see ElevationProfileBase
+ * @see ElevationModel
+ * @see ElevationProfileLeaf
+ */
+public class ElevationProfileNode extends ElevationProfileBase {
+	private List<IElevationProfile> slices;
+	
+	/**
+	 * Creates a new elevation track model.
+	 * @param trackName The name of the track.
+	 * @param parent The parent elevation profile
+	 * @param sliceSize The (maximum) size of each slice.
+	 * @param wayPoints The way points belonging to this track.
+	 */
+	public ElevationProfileNode(String trackName, IElevationProfile parent, List<WayPoint> wayPoints, int sliceSize) {
+		super(trackName, parent, wayPoints, sliceSize);
+		setSliceSize(sliceSize);
+		// ensure that sliceSize has a reasonable value
+		createsSlices(wayPoints);
+	}
+
+	/**
+	 * Notifies listeners that the active slice has been changed.
+	 * 
+	 * @param oldIndex
+	 *            The index of the previously selected slice.
+	 * @param newIndex
+	 *            The index of the current slice.
+	 * 
+	 *            private void fireSliceChanged(int oldIndex, int newIndex) { if
+	 *            (listeners == null || listeners.size() == 0) { return; }
+	 * 
+	 *            if (!checkIndex(newIndex)) { throw new
+	 *            IndexOutOfBoundsException(
+	 *            String.format("Invalid index: %d (expected 0-%d)", newIndex,
+	 *            getNumberOfSlices())); } ElevationModelSlice oldObj =
+	 *            getSliceAt(oldIndex); ElevationModelSlice newObj =
+	 *            getSliceAt(newIndex);
+	 * 
+	 *            for (IElevationModelSliceListener listener : listeners) {
+	 *            listener.sliceSelectionChanged(oldObj, newObj); } }
+	 */
+
+	/**
+	 * Gets the number of slices.
+	 * 
+	 * @return
+	 */
+	public int getNumberOfSlices() {
+		return slices != null ? slices.size() : 0;
+	}
+
+	/**
+	 * Assign other way points to this track.
+	 * 
+	 * @param waypoints
+	 *            The list containing the way points.
+	 */
+	public void updateTrack(List<WayPoint> waypoints) {
+		createsSlices(waypoints);
+	}
+
+	/**
+	 * Creates the track slices.
+	 * 
+	 * @param wayPoints
+	 *            The way points of the track.
+	 */
+	private void createsSlices(List<WayPoint> wayPoints) {
+		if (wayPoints == null || getSliceSize() <= 0) {
+			return;
+		}
+
+		if (slices == null) {
+			slices = new ArrayList<IElevationProfile>();
+		} else {
+			slices.clear();
+		}
+
+		for (int i = 0; i < wayPoints.size(); i += getSliceSize()) {
+			int to = Math.min(i + getSliceSize(), wayPoints.size());
+			ElevationProfileLeaf ems = new ElevationProfileLeaf(getName(), this, wayPoints.subList(i, to));
+			slices.add(ems);
+		}
+		
+		// downsample
+		setWayPoints(ElevationHelper.downsampleWayPoints(wayPoints, getSliceSize()), false);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.ElevationProfileBase#getChildren()
+	 */
+	@Override
+	public List<IElevationProfile> getChildren() {
+		return slices;
+	}
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationWayPointKind.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationWayPointKind.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationWayPointKind.java	(revision 29907)
@@ -0,0 +1,35 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+/**
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * Enumeration which classifies way points within an elevation profile.
+ */
+public enum ElevationWayPointKind {
+	Plain, 				// Simple way point (equal to no or low slope)
+	Highlighted,			// Highlighted waypoint
+	StartPoint,			// First way point
+	EndPoint,			// Last way point
+	MaxElevation,			// Highest way point
+	MinElevation,			// Lowest way point 
+	ElevationGainHigh,		// Elevation gain (high slope 15-25%)
+	ElevationLossHigh,		// Elevation loss (high downward slope)
+	ElevationGainLow,		// Elevation gain (low slope, 5-14.9%)
+	ElevationLossLow,		// Elevation loss (low downward slope)
+	ElevationLevelGain,		// Elevation level gain (e. g. crossed 300m from lower elevation)
+	ElevationLevelLoss,		// Elevation level (e. g. crossed 300m from higher elevation)
+	FullHour			// Full Hour	
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GeoidCorrectionKind.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GeoidCorrectionKind.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GeoidCorrectionKind.java	(revision 29907)
@@ -0,0 +1,28 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+/**
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * Enumeration for available elevation correction modes. 
+ */
+public enum GeoidCorrectionKind {
+	/** Elevation values remain unchanged */
+	None,
+	/** Automatic correction by geoid lookup table */
+	Auto,
+	/** Fixed value */
+	Fixed
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GpxIterator.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GpxIterator.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GpxIterator.java	(revision 29907)
@@ -0,0 +1,140 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import java.util.Collection;
+
+import org.openstreetmap.josm.data.gpx.GpxData;
+import org.openstreetmap.josm.data.gpx.GpxRoute;
+import org.openstreetmap.josm.data.gpx.GpxTrack;
+import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+/**
+ * Utility class to apply a visitor on GPX containers (track, route, data).
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ */
+public class GpxIterator {
+	/**
+	 * Static class, no need to instantiate me.
+	 */
+	private GpxIterator() {}
+	
+	/**
+	 * Runs the given visitor on a GPX data instance. If one or both 
+	 * arguments are null, this method will return immediately. 
+	 * 
+	 * @param data
+	 *            The GPX data instance.
+	 * @param visitor
+	 *            The visitor which inspects all GPX entities.
+	 */
+	public static void visit(GpxData data, IGpxVisitor visitor) {
+		if (data == null) return;
+		if (visitor == null) return;
+		
+		visitor.start();
+		visitSingleWaypoints(data, visitor);
+		visitor.end();
+
+		// routes
+		if (data.hasRoutePoints()) {
+			for (GpxRoute rte : data.routes) {
+				visitRoute(visitor, rte);
+			}
+		}
+
+		// tracks
+		for (GpxTrack trk : data.tracks) {
+			visitTrack(visitor, trk);
+		}
+	}
+	
+	/**
+	 * Visits a single GPX track. 
+	 * @param track The track to visit.
+	 * @param visitor
+	 *            The visitor which inspects all GPX entities.
+	 */
+	public static void visit(GpxTrack track, IGpxVisitor visitor) {
+		visitTrack(visitor, track);
+	}
+	
+	/**
+	 * Visits a single GPX route. 
+	 * @param route The route to visit.
+	 * @param visitor
+	 *            The visitor which inspects all GPX entities.
+	 */
+	public static void visit(GpxRoute route, IGpxVisitor visitor) {
+		visitRoute(visitor, route);
+	}
+
+	// ---------------------- Helper methods ----------------
+	
+	/**
+	 * @param visitor
+	 * @param trk
+	 */
+	private static void visitTrack(IGpxVisitor visitor, GpxTrack trk) {
+		if (trk == null) return;
+		if (visitor == null) return;
+		
+		Collection<GpxTrackSegment> segments = trk.getSegments();
+		visitor.start();
+
+		if (segments != null) {
+			for (GpxTrackSegment segment : segments) {
+				Collection<WayPoint> waypts = segment.getWayPoints();
+				// no visitor here...
+				if (waypts == null)
+					continue;
+
+				for (WayPoint wayPoint : waypts) {
+					visitor.visit(wayPoint);
+				}
+			}
+		}
+		visitor.end();
+	}
+
+	/**
+	 * @param visitor
+	 * @param route
+	 */
+	private static void visitRoute(IGpxVisitor visitor, GpxRoute route) {
+		if (route == null) return;
+		if (visitor == null) return;
+		
+		visitor.start();
+		for (WayPoint wpt : route.routePoints) {
+			visitor.visit(wpt);
+		}
+		visitor.end();
+	}
+
+	/**
+	 * @param data
+	 * @param visitor
+	 */
+	private static void visitSingleWaypoints(GpxData data, IGpxVisitor visitor) {
+		// isolated way points
+		if (data.waypoints != null) { // better with an hasWaypoints method!?
+			for (WayPoint wpt : data.waypoints) {
+				visitor.visit(wpt);
+			}
+		}
+	}
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxVisitor.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxVisitor.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxVisitor.java	(revision 29907)
@@ -0,0 +1,40 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+/**
+ * Interface for all GPX visitors.
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ */
+public interface IGpxVisitor extends IGpxWaypointVisitor {
+	/**
+	 * Starts a GPX route, track or way point collection.
+	 */
+	void start();
+	
+	/**
+	 * Ends a GPX route, track or way point collection.
+	 */
+	void end();
+	
+	/**
+	 * Visits a way point within a GPX route.
+	 * @param route The route containing the way point.
+	 * @param wp The way point to visit.
+	 */
+	void visit(WayPoint wp);
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxWaypointVisitor.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxWaypointVisitor.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxWaypointVisitor.java	(revision 29907)
@@ -0,0 +1,30 @@
+/**
+ * This program is free software: you can redistribute it and/or modify it under 
+ * the terms of the GNU General Public License as published by the 
+ * Free Software Foundation, either version 3 of the License, or 
+ * (at your option) any later version. 
+ * 
+ * This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; 
+ * without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. 
+ * See the GNU General Public License for more details. 
+ * 
+ * You should have received a copy of the GNU General Public License along with this program. 
+ * If not, see <http://www.gnu.org/licenses/>.
+ */
+
+package org.openstreetmap.josm.plugins.elevation.gpx;
+
+import org.openstreetmap.josm.data.gpx.WayPoint;
+
+/**
+ * @author Oliver Wieland <oliver.wieland@online.de>
+ * Interface for all GPX data visitors. Hopefully this will be part of JOSM some day.
+ */
+public interface IGpxWaypointVisitor {
+	/**
+	 * Visits a way point. This method is called for isolated way points, i. e. way points
+	 * without an associated route or track. 
+	 * @param wp The way point to visit.
+	 */
+	void visit(WayPoint wp);
+}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/DefaultElevationProfileRenderer.java	(revision 29907)
@@ -32,7 +32,7 @@
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind;
 import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
-import org.openstreetmap.josm.plugins.elevation.WayPointHelper;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationWayPointKind;
 import org.openstreetmap.josm.tools.CheckParameterUtil;
 
@@ -88,5 +88,5 @@
 		}
 
-		int z = (int) WayPointHelper.getElevation(wpt);
+		int z = (int) ElevationHelper.getElevation(wpt);
 
 		switch (kind) {
@@ -192,5 +192,5 @@
 
 		Point pnt = mv.getPoint(wpt.getEastNorth());
-		int ele = ((int) Math.rint(WayPointHelper.getElevation(wpt) / 100.0)) * 100;
+		int ele = ((int) Math.rint(ElevationHelper.getElevation(wpt) / 100.0)) * 100;
 		
 		int rad = REGULAR_WPT_RADIUS;
@@ -200,5 +200,5 @@
 		/* Paint full hour label */
 		if (kind == ElevationWayPointKind.FullHour) {
-			int hour = WayPointHelper.getHourOfWayPoint(wpt);
+			int hour = ElevationHelper.getHourOfWayPoint(wpt);
 			drawLabel(String.format("%02d:00", hour), pnt.x, pnt.y
 					+ g.getFontMetrics().getHeight(), g);
@@ -207,5 +207,5 @@
 		/* Paint label for elevation levels */
 		if (kind == ElevationWayPointKind.ElevationLevelGain) {
-			drawLabelWithTriangle(WayPointHelper.getElevationText(ele), pnt.x, pnt.y
+			drawLabelWithTriangle(ElevationHelper.getElevationText(ele), pnt.x, pnt.y
 					+ g.getFontMetrics().getHeight(), g, c, 8, 
 					getColorForWaypoint(profile, wpt, ElevationWayPointKind.ElevationGainHigh),
@@ -214,5 +214,5 @@
 		
 		if (kind == ElevationWayPointKind.ElevationLevelLoss) {
-			drawLabelWithTriangle(WayPointHelper.getElevationText(ele), 
+			drawLabelWithTriangle(ElevationHelper.getElevationText(ele), 
 					pnt.x, pnt.y+ g.getFontMetrics().getHeight(), g, c, 8, 
 					getColorForWaypoint(profile, wpt, ElevationWayPointKind.ElevationLossHigh),
@@ -223,7 +223,7 @@
 		if (kind == ElevationWayPointKind.Highlighted) {
 			drawSphere(g, Color.WHITE, c, pnt.x, pnt.y, BIG_WPT_RADIUS);
-			drawLabel(WayPointHelper.getTimeText(wpt), pnt.x, pnt.y
+			drawLabel(ElevationHelper.getTimeText(wpt), pnt.x, pnt.y
 					- g.getFontMetrics().getHeight() - 5, g);
-			drawLabel(WayPointHelper.getElevationText(wpt), pnt.x, pnt.y
+			drawLabel(ElevationHelper.getElevationText(wpt), pnt.x, pnt.y
 					+ g.getFontMetrics().getHeight() + 5, g);
 		}
@@ -248,5 +248,5 @@
 
 		Color c = getColorForWaypoint(profile, wpt, kind);
-		int eleH = (int) WayPointHelper.getElevation(wpt);
+		int eleH = (int) ElevationHelper.getElevation(wpt);
 		Point pnt = mv.getPoint(wpt.getEastNorth());
 
@@ -273,5 +273,5 @@
 				DefaultElevationProfileRenderer.TRIANGLE_BASESIZE);
 
-		drawLabel(WayPointHelper.getElevationText(eleH), pnt.x, pnt.y
+		drawLabel(ElevationHelper.getElevationText(eleH), pnt.x, pnt.y
 				+ g.getFontMetrics().getHeight(), g, c);
 	}
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationColors.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationColors.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationColors.java	(revision 29907)
@@ -17,4 +17,6 @@
 import java.awt.Color;
 
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+
 /**
  * Contains some extra predefined colors. 
@@ -30,3 +32,82 @@
 	public static Color EPLightBeige = new Color(235, 235, 215);
 	public static Color EPMidBeige = new Color(227, 222, 215);
+	
+		
+	static class ColorMapEntry {
+	    private int ele; // limit
+	    private Color color;
+	    public ColorMapEntry(java.awt.Color color, int ele) {
+		super();
+		this.color = color;
+		this.ele = ele;
+	    }
+	    
+	    public int getEle() {
+	        return ele;
+	    }
+	    
+	    public Color getColor() {
+	        return color;
+	    }
+	}
+	
+	private static ColorMapEntry[] colors = new ColorMapEntry[]{
+		  new ColorMapEntry(new Color(0,128, 0), 0),  
+		  new ColorMapEntry(new Color(156,187, 105), 1),  
+		  new ColorMapEntry(new Color(193,208, 107), 100),
+		  new ColorMapEntry(new Color(244,224, 100), 200),
+		  new ColorMapEntry(new Color(242,216, 149), 500),
+		  new ColorMapEntry(new Color(234,191, 104), 1000),
+		  new ColorMapEntry(new Color(207,169, 96), 2000),
+		};
+	
+	public static Color interpolate(java.awt.Color c1, java.awt.Color c2) {
+	    int r = (c1.getRed() + c2.getRed()) / 2;
+	    int g = (c1.getGreen() + c2.getGreen()) / 2;
+	    int b = (c1.getBlue() + c2.getBlue()) / 2;
+	    return new Color(r, g, b);
+	}
+	
+	public static Color getElevationColor(double ele) {
+	    if (!ElevationHelper.isValidElevation(ele)) {
+		return Color.white;
+	    }
+	   
+	    // TODO: Better color model...
+	    Color col = Color.green;
+	    
+	    if (ele < 0) {
+		col = Color.blue;
+	    }
+	    
+	    if (ele > 200) {
+		col = colors[1].getColor(); 
+	    }
+	    
+	    if (ele > 300) {
+		col = colors[2].getColor(); 
+	    }
+	    
+	    if (ele > 400) {
+		col = colors[3].getColor(); 
+	    }
+	    
+	    if (ele > 500) {
+		col = Color.yellow; 
+	    }
+	    
+	    if (ele > 750) {
+		col = Color.orange; 
+	    }
+	    
+	    if (ele > 1000) {
+		col = Color.lightGray; 
+	    }
+	    
+	    if (ele > 2000) {
+		col = Color.darkGray; 
+	    }
+	    
+	    return col;
+	}
 }
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileDialog.java	(revision 29907)
@@ -40,8 +40,8 @@
 import org.openstreetmap.josm.gui.layer.GpxLayer;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.plugins.elevation.ElevationModel;
-import org.openstreetmap.josm.plugins.elevation.GeoidCorrectionKind;
 import org.openstreetmap.josm.plugins.elevation.IElevationModelListener;
-import org.openstreetmap.josm.plugins.elevation.WayPointHelper;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationModel;
+import org.openstreetmap.josm.plugins.elevation.gpx.GeoidCorrectionKind;
 import org.openstreetmap.josm.tools.Shortcut;
 
@@ -170,5 +170,5 @@
 		geoidNone.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent arg0) {
-				WayPointHelper.setGeoidKind(GeoidCorrectionKind.None);
+				ElevationHelper.setGeoidKind(GeoidCorrectionKind.None);
 				geoidFixedValue.setEnabled(false);
 				getModel().updateElevationData();
@@ -180,5 +180,5 @@
 		geoidAuto.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent arg0) {
-				WayPointHelper.setGeoidKind(GeoidCorrectionKind.Auto);
+				ElevationHelper.setGeoidKind(GeoidCorrectionKind.Auto);
 				geoidFixedValue.setEnabled(false);
 				getModel().updateElevationData();
@@ -191,5 +191,5 @@
 		geoidFixed.addActionListener(new ActionListener() {
 			public void actionPerformed(ActionEvent arg0) {
-				WayPointHelper.setGeoidKind(GeoidCorrectionKind.Fixed);
+				ElevationHelper.setGeoidKind(GeoidCorrectionKind.Fixed);
 				geoidFixedValue.setEnabled(true);
 				getModel().updateElevationData();
@@ -220,8 +220,8 @@
 		profPanel.addComponentListener(this);
 
-		if (WayPointHelper.getGeoidKind() == GeoidCorrectionKind.Auto) {
+		if (ElevationHelper.getGeoidKind() == GeoidCorrectionKind.Auto) {
 			geoidAuto.setSelected(true);
 		}
-		if (WayPointHelper.getGeoidKind() == GeoidCorrectionKind.Fixed) {
+		if (ElevationHelper.getGeoidKind() == GeoidCorrectionKind.Fixed) {
 			geoidFixed.setSelected(true);
 		}
@@ -301,11 +301,11 @@
 				// Show elevation data
 				minHeightLabel.setText(
-						WayPointHelper.getElevationText(profile.getMinHeight()));
+						ElevationHelper.getElevationText(profile.getMinHeight()));
 				maxHeightLabel.setText(
-						WayPointHelper.getElevationText(profile.getMaxHeight()));
+						ElevationHelper.getElevationText(profile.getMaxHeight()));
 				avrgHeightLabel.setText(
-						WayPointHelper.getElevationText(profile.getAverageHeight()));
+						ElevationHelper.getElevationText(profile.getAverageHeight()));
 				elevationGainLabel.setText(
-						WayPointHelper.getElevationText(profile.getGain()));
+						ElevationHelper.getElevationText(profile.getGain()));
 			}
 			
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileLayer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileLayer.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfileLayer.java	(revision 29907)
@@ -29,7 +29,7 @@
 import org.openstreetmap.josm.gui.dialogs.LayerListPopup;
 import org.openstreetmap.josm.gui.layer.Layer;
-import org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind;
 import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
-import org.openstreetmap.josm.plugins.elevation.WayPointHelper;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationWayPointKind;
 import org.openstreetmap.josm.tools.ImageProvider;
 
@@ -173,5 +173,5 @@
 
 		// remember some things for next iteration
-		lastEle = (int) WayPointHelper.getElevation(wpt);
+		lastEle = (int) ElevationHelper.getElevation(wpt);
 		lastWpt = wpt;
 	    }
@@ -212,11 +212,11 @@
     private ElevationWayPointKind classifyWayPoint(WayPoint lastWpt, WayPoint actWpt) {
 	// get elevation values
-	int actEle = (int) WayPointHelper.getElevation(actWpt);
-	int lastEle = (int) WayPointHelper.getElevation(lastWpt);
+	int actEle = (int) ElevationHelper.getElevation(actWpt);
+	int lastEle = (int) ElevationHelper.getElevation(lastWpt);
 	
 	// normalize elevation to levels
 	int actLevel = (int)(actEle / Level_Factor);
 	int lastLevel = (int)(lastEle / Level_Factor);
-	double slope = Math.abs(WayPointHelper.computeSlope(lastWpt, actWpt));
+	double slope = Math.abs(ElevationHelper.computeSlope(lastWpt.getCoor(), actWpt.getCoor()));
 
 	// plain way point by default
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/ElevationProfilePanel.java	(revision 29907)
@@ -37,7 +37,7 @@
 
 import org.openstreetmap.josm.data.gpx.WayPoint;
-import org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind;
 import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
-import org.openstreetmap.josm.plugins.elevation.WayPointHelper;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationWayPointKind;
 
 /**
@@ -289,5 +289,5 @@
 			// check bounds
 			if (yLine <= getPlotBottom() && yLine >= getPlotTop()) {
-				String txt = WayPointHelper.getElevationText(i);
+				String txt = ElevationHelper.getElevationText(i);
 				
 				Rectangle r = drawAlignedString(txt, getPlotHCenter(), yLine - 2,
@@ -399,5 +399,5 @@
 		for (int i = 0; i < n; i++) {
 			WayPoint wpt = profile.getWayPoints().get(i);
-			int eleVal = (int) WayPointHelper.getElevation(wpt);
+			int eleVal = (int) ElevationHelper.getElevation(wpt);
 			Color c = renderer.getColorForWaypoint(profile, wpt,
 					ElevationWayPointKind.Plain);
@@ -405,5 +405,5 @@
 			if (i == this.selectedIndex) {
 				g.setColor(Color.BLACK);
-				drawAlignedString(WayPointHelper.getElevationText(eleVal), 
+				drawAlignedString(ElevationHelper.getElevationText(eleVal), 
 						(getPlotRight() + getPlotLeft()) / 2, 
 						getPlotBottom() + 6, 
@@ -420,6 +420,6 @@
 			
 			int geoidVal = 0;
-			switch(WayPointHelper.getGeoidKind()) {
-				case Auto: geoidVal = WayPointHelper.getGeoidCorrection(wpt); break;
+			switch(ElevationHelper.getGeoidKind()) {
+				case Auto: geoidVal = ElevationHelper.getGeoidCorrection(wpt); break;
 				case Fixed: // not impl
 			}
@@ -532,5 +532,5 @@
 		WayPoint wpt = getSelectedWayPoint();
 		if (wpt != null) {
-			return  String.format("%s: %s", WayPointHelper.getTimeText(wpt), WayPointHelper.getElevationText(wpt));
+			return  String.format("%s: %s", ElevationHelper.getTimeText(wpt), ElevationHelper.getElevationText(wpt));
 		}
 		
Index: /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/IElevationProfileRenderer.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/IElevationProfileRenderer.java	(revision 29906)
+++ /applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gui/IElevationProfileRenderer.java	(revision 29907)
@@ -20,6 +20,6 @@
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.gui.MapView;
-import org.openstreetmap.josm.plugins.elevation.ElevationWayPointKind;
 import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+import org.openstreetmap.josm.plugins.elevation.gpx.ElevationWayPointKind;
 
 /**
Index: /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/EleVertexTest.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/EleVertexTest.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/EleVertexTest.java	(revision 29907)
@@ -0,0 +1,93 @@
+package org.openstreetmap.josm.plugins.elevation.tests;
+
+import java.util.List;
+
+import junit.framework.TestCase;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Bounds;
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.elevation.EleCoordinate;
+import org.openstreetmap.josm.plugins.elevation.EleVertex;
+import org.openstreetmap.josm.plugins.elevation.ElevationRenderer;
+
+public class EleVertexTest extends TestCase {
+
+    /**
+     * Setup test.
+     */
+    public void setUp() {
+        Main.pref = new Preferences();
+    }
+    
+    public void testDivide() {
+	EleCoordinate p1 = new EleCoordinate(30.0, 30.0, 100.0);
+	EleCoordinate p2 = new EleCoordinate(35.0, 30.0, 120.0);
+	EleCoordinate p3 = new EleCoordinate(35.0, 40.0, 110.0);
+	EleVertex ev = new EleVertex(p1, p2, p3);
+	
+	List<EleVertex> list = ev.divide();
+	
+	assertEquals(2, list.size());
+	
+	// 1st vertex (p1, p2, pN  105m) 
+	EleVertex v1 = list.get(0);
+	assertEquals(325 / 3D, v1.getEle());
+	assertCoorEq(v1, 30D, 30D, 0);
+	assertCoorEq(v1, 30D, 35D, 1);
+	assertCoorEq(v1, 35D, 32.5D, 2);
+	
+	// 2nd vertex (p3, p2, pN = 105m) 
+	EleVertex v2 = list.get(1);
+	
+	assertEquals(335/3D, v2.getEle());
+	assertCoorEq(v2, 40D, 35D, 0);
+	assertCoorEq(v2, 30D, 35D, 1);
+	assertCoorEq(v2, 35D, 32.5D, 2);
+    }
+    
+    public void testSimpleRecurse() {
+	EleCoordinate c1 = new EleCoordinate(new LatLon(50.8328, 8.1337), 300);
+	EleCoordinate c2 = new EleCoordinate(new LatLon(50.8328, 7.9217), 200);
+	EleCoordinate c3 = new EleCoordinate(new LatLon(50.9558, 7.9217), 400);
+	EleCoordinate c4 = new EleCoordinate(new LatLon(50.5767627, 9.1938483), 100);
+	
+	EleVertex v1 = new EleVertex(c1, c2, c3);
+	System.out.println("Start recurse");
+	recurse(v1, 0);
+    }
+    
+    private void recurse(EleVertex v, int depth) {
+	if (!v.isFinished() && depth <100) {
+	    System.out.println("\tDivide: " + v);
+	    List<EleVertex> list = v.divide();
+	    assertNotNull(list);
+	    assertEquals(2, list.size());
+	    assertTrue(depth < 50); //, "Too many recursions?");	    
+	    for (EleVertex eleVertex : list) {
+		//System.out.println("\t\tRecurse: " + eleVertex);
+		assertTrue("Area is larger " + v.getArea() + " > " + eleVertex.getArea(), eleVertex.getArea() < v.getArea());
+		recurse(eleVertex, depth + 1);
+	    }
+	} else {
+	    System.out.println("Finished: " + depth);
+	}
+    }
+    
+    public void testRenderer() {
+	
+	// Staufenberg, Hessen
+	// Ulrichstein, Hessen
+	ElevationRenderer er = new ElevationRenderer("Ele", new Bounds(
+		new LatLon(50.6607106, 8.7337029), 
+		new LatLon(50.5767627, 9.1938483)), null);
+	
+	er.run();
+    }
+
+    private void assertCoorEq(EleVertex v1, double x, double y, int n) {
+	assertEquals(x, v1.get(n).getX());
+	assertEquals(y, v1.get(n).getY());
+    }
+}
Index: /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/HgtReaderTest.java
===================================================================
--- /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/HgtReaderTest.java	(revision 29907)
+++ /applications/editors/josm/plugins/ElevationProfile/test/org/openstreetmap/josm/plugins/elevation/tests/HgtReaderTest.java	(revision 29907)
@@ -0,0 +1,44 @@
+package org.openstreetmap.josm.plugins.elevation.tests;
+
+
+
+import junit.framework.TestCase;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.Preferences;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.plugins.elevation.HgtReader;
+
+public class HgtReaderTest extends TestCase {
+
+    /**
+     * Setup test.
+     */
+    public void setUp() {
+        Main.pref = new Preferences();
+    }
+
+    public void testGetElevationFromHgt() {
+	// Staufenberg, Hessen
+	testHgtData(50.6607106, 8.7337029, "N50E008.hgt", 199);
+	// Ulrichstein, Hessen
+	testHgtData(50.5767627, 9.1938483, "N50E009.hgt", 560);
+	// Fujijama
+	//testHgtData(35.360555, 138.727777, "N35E138.hgt", 3741);
+    }
+
+    private void testHgtData(final double lat, final double lon,
+	    final String expTag, final int expHeight) {
+	LatLon l = new LatLon(lat, lon);
+	HgtReader hr = new HgtReader();
+	String text = hr.getHgtFileName(l);
+	
+	assertEquals(expTag, text);
+	
+	double d = hr.getElevationFromHgt(l);
+	System.out.println(d);
+	assertFalse("Data missing or void for coor " + l, Double.isNaN(d));
+	
+	assertEquals((int)d, expHeight);
+    }
+}
