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 29961)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationModel.java	(revision 29962)
@@ -22,4 +22,5 @@
 import org.openstreetmap.josm.data.gpx.GpxTrack;
 import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
+import org.openstreetmap.josm.data.gpx.IWithAttributes;
 import org.openstreetmap.josm.data.gpx.WayPoint;
 import org.openstreetmap.josm.plugins.elevation.IElevationModel;
@@ -44,5 +45,5 @@
 	private List<WayPoint> buffer = new ArrayList<WayPoint>();
 	private int currentProfileIndex = 0;
-	private ElevationProfileBase curProfile = null;
+	private ElevationProfile curProfile = null;
 
 	/**
@@ -115,27 +116,69 @@
 	}
 
-	/*
-	 * (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) {
-	    	// we ignore the segment here 
-		processWayPoint(wp);
-		
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#getProfiles()
+	 */
+	@Override
+	public List<IElevationProfile> getProfiles() {
+		return profiles;
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#getCurrentProfile()
+	 */
+	@Override
+	public IElevationProfile getCurrentProfile() {
+	    if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null;
+	    
+	    return profiles.get(currentProfileIndex);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#setCurrentProfile(org.openstreetmap.josm.plugins.elevation.IElevationProfile)
+	 */
+	@Override
+	public void setCurrentProfile(IElevationProfile newProfile) {
+	    CheckParameterUtil.ensureParameterNotNull(newProfile);
+	    
+	    if (!profiles.contains(newProfile)) {
+		profiles.add(newProfile);
+	    }
+	    
+	    setCurrentProfile(profiles.indexOf(newProfile)); 
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#setCurrentProfile(int)
+	 */
+	@Override
+	public void setCurrentProfile(int index) {
+	    if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount());
+	    
+	    currentProfileIndex = index;
+	    fireModelChanged();	    
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.IElevationModel#profileCount()
+	 */
+	@Override
+	public int profileCount() {
+	    return profiles != null ? profiles.size() : 0;
+	}
+
+	// Visitor stuff starts here...
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginWayPoints()
+	 */
+	public void beginWayPoints() {
+	    // we ignore single way points (elevation profile is quite meaningless...)
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endWayPoints()
+	 */
+	public void endWayPoints() {		
+	    // we ignore single way points (elevation profile is quite meaningless...)
 	}
 	
@@ -144,26 +187,94 @@
 	 */
 	@Override
-	public void visit(WayPoint wp) {
-		processWayPoint(wp);
-	}
-
-	public void start() {
-		curProfile = new ElevationProfileBase(name);
-		trackCounter++;
-	}
-
-	public void end() {		
-		commitTrack();
-	}
-	
-
-	@Override
-	public void start(GpxTrack track) {
+	public void visitWayPoint(WayPoint wp) {
+	    // we ignore single way points (elevation profile is quite meaningless...)
+	}
+
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginTrack(org.openstreetmap.josm.data.gpx.GpxTrack)
+	 */
+	@Override
+	public void beginTrack(GpxTrack track) {
+	    createProfile(track);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endTrack(org.openstreetmap.josm.data.gpx.GpxTrack)
+	 */
+	@Override
+	public void endTrack(GpxTrack track) {
+	    if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
+	    
+	    curProfile.setDistance(track.length());
+	    commitProfile();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginTrackSegment(org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment)
+	 */
+	@Override
+	public void beginTrackSegment(GpxTrack track, GpxTrackSegment segment) {
+	    // Nothing to do here for now
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endTrackSegment(org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment)
+	 */
+	@Override
+	public void endTrackSegment(GpxTrack track, GpxTrackSegment segment) {
+	    // Nothing to do here for now
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#visitTrackPoint(org.openstreetmap.josm.data.gpx.WayPoint, org.openstreetmap.josm.data.gpx.GpxTrack, org.openstreetmap.josm.data.gpx.GpxTrackSegment)
+	 */
+	@Override
+	public void visitTrackPoint(WayPoint wp, GpxTrack track,
+		GpxTrackSegment segment) {
+	    
+	    processWayPoint(wp);	    
+	}
+	
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#beginRoute(org.openstreetmap.josm.data.gpx.GpxRoute)
+	 */
+	@Override
+	public void beginRoute(GpxRoute route) {
+	    createProfile(route);
+	}
+
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#endRoute(org.openstreetmap.josm.data.gpx.GpxRoute)
+	 */
+	@Override
+	public void endRoute(GpxRoute route) {
+	    if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
+	    // a GpxRoute has no 'length' property 
+	    curProfile.setDistance(0);
+	    commitProfile();
+	}
+	
+	/* (non-Javadoc)
+	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IGpxVisitor#visitRoutePoint(org.openstreetmap.josm.data.gpx.WayPoint, org.openstreetmap.josm.data.gpx.GpxRoute)
+	 */
+	@Override
+	public void visitRoutePoint(WayPoint wp, GpxRoute route) {
+	    processWayPoint(wp);	    
+	}
+	
+	/**
+	 * Creates a new profile.
+	 *
+	 * @param trackOrRoute the track or route
+	 */
+	private void createProfile(IWithAttributes trackOrRoute) {
 	    // check GPX data 
-	    String trackName = (String) track.get("name");
+	    String trackName = (String) trackOrRoute.get("name");
 	    
 	    // no name given, build artificial one
 	    if (trackName == null) {
-		trackName = (String) track.get(GpxData.META_NAME);
+		trackName = (String) trackOrRoute.get(GpxData.META_NAME);
 		if (trackName == null) {
 		    trackName = name + "." + trackCounter;
@@ -171,25 +282,6 @@
 	    }
 	    
-	    curProfile = new ElevationProfileBase(trackName);
-	}
-
-	@Override
-	public void end(GpxTrack track) {
-	    if (curProfile == null) throw new RuntimeException("Internal error: No elevation profile");
-	    
-	    curProfile.setDistance(track.length());
-	    commitTrack();
-	}
-	
-	@Override
-	public void start(GpxTrack track, GpxTrackSegment segment) {
-	    // Nothing to do here for now
-	}
-
-	@Override
-	public void end(GpxTrack track, GpxTrackSegment segment) {
-	    // Nothing to do here for now
-	}
-
+	    curProfile = new ElevationProfile(trackName);
+	}
 	
 	/**
@@ -198,5 +290,5 @@
 	 * @param trackName the track name
 	 */
-	private void commitTrack() {
+	private void commitProfile() {
 	    	if (buffer.size() > 0) {    
 	    	    	// assign way points to profile...
@@ -208,4 +300,9 @@
 	}
 
+	/**
+	 * Adds the given way point to the current buffer.
+	 *
+	 * @param wp the wp
+	 */
 	private void processWayPoint(WayPoint wp) {
 		if (wp == null) {
@@ -215,43 +312,3 @@
 		buffer.add(wp);
 	}
-
-	
-	/* (non-Javadoc)
-	 * @see org.openstreetmap.josm.plugins.elevation.gpx.IElevationModel#getProfiles()
-	 */
-	@Override
-	public List<IElevationProfile> getProfiles() {
-		return profiles;
-	}
-
-	@Override
-	public IElevationProfile getCurrentProfile() {
-	    if (currentProfileIndex < 0 || currentProfileIndex >= profileCount()) return null;
-	    
-	    return profiles.get(currentProfileIndex);
-	}
-
-	@Override
-	public void setCurrentProfile(IElevationProfile newProfile) {
-	    CheckParameterUtil.ensureParameterNotNull(newProfile);
-	    
-	    if (!profiles.contains(newProfile)) {
-		profiles.add(newProfile);
-	    }
-	    
-	    setCurrentProfile(profiles.indexOf(newProfile)); 
-	}
-
-	@Override
-	public void setCurrentProfile(int index) {
-	    if (index < 0 || index >= profileCount()) throw new RuntimeException("Invalid arg for setCurrentProfile: " + index + ", value must be 0.." + profileCount());
-	    
-	    currentProfileIndex = index;
-	    fireModelChanged();	    
-	}
-
-	@Override
-	public int profileCount() {
-	    return profiles != null ? profiles.size() : 0;
-	}
 }
Index: applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java
===================================================================
--- applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 29962)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/ElevationProfile.java	(revision 29962)
@@ -0,0 +1,529 @@
+/**
+ * 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.Bounds;
+import org.openstreetmap.josm.data.gpx.WayPoint;
+import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
+import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
+
+/**
+ * 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 ElevationProfile#visitWayPoint(WayPoint)}
+ * method to compute own values or run specific actions. The computation is
+ * triggered by calling {@link ElevationProfile#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 class ElevationProfile 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 gain;
+	private int lastEle;
+	private Bounds bounds;
+	
+	private static boolean ignoreZeroHeight = true;
+
+	/**
+	 * Creates a name elevation profile without any way points.
+	 * 
+	 * @param name
+	 */
+	public ElevationProfile(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 ElevationProfile(String name, IElevationProfile parent,
+			List<WayPoint> wayPoints, int sliceSize) {
+		super();
+		this.name = name;
+		this.parent = parent;
+		
+		setWayPoints(wayPoints);
+	}
+
+	/**
+	 * Checks if zero elevation should be ignored or not.
+	 *
+	 * @return true, if is ignore zero height
+	 */
+	public static boolean isIgnoreZeroHeight() {
+		return ignoreZeroHeight;
+	}
+
+	/**
+	 * Sets the ignore zero height.
+	 *
+	 * @param ignoreZeroHeight the new ignore zero height
+	 */
+	public static void setIgnoreZeroHeight(boolean ignoreZeroHeight) {
+		ElevationProfile.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) {
+			visitWayPoint(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) {
+		if (this.wayPoints != wayPoints) {
+			this.wayPoints = new ArrayList<WayPoint>(wayPoints);
+			numWayPoints = wayPoints != null ? wayPoints.size() : 0;
+			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()));
+		}
+	}
+
+	/*
+	 * (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 List<IElevationProfile> getChildren() {
+	    return null;
+	}
+
+	/*
+	 * (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 the coordinate bounds of this profile. See {@link Bounds} for details.
+	 *
+	 * @return the bounds of this elevation profile
+	 */
+	public Bounds getBounds() {
+	    return bounds;
+	}
+
+	/**
+	 * 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 visitWayPoint(WayPoint wp) {
+		if (wp.getTime().after(end)) {
+			setEnd(wp);
+		}
+
+		if (wp.getTime().before(start)) {
+			setStart(wp);
+		}
+
+		// update boundaries
+		if (bounds == null) {
+		    bounds = new Bounds(wp.getCoor());
+		} else {
+		    bounds.extend(wp.getCoor());
+		}
+		
+		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 name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
+				+ ", minHeight=" + getMinHeight() + ", maxHeight="
+				+ getMaxHeight() + "]";*/
+	}
+}
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 29961)
+++ 	(revision )
@@ -1,529 +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.gpx;
-
-import java.util.ArrayList;
-import java.util.Date;
-import java.util.List;
-
-import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.gpx.WayPoint;
-import org.openstreetmap.josm.plugins.elevation.ElevationHelper;
-import org.openstreetmap.josm.plugins.elevation.IElevationProfile;
-
-/**
- * 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 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 gain;
-	private int lastEle;
-	private Bounds bounds;
-	
-	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;
-		
-		setWayPoints(wayPoints);
-	}
-
-	/**
-	 * Checks if zero elevation should be ignored or not.
-	 *
-	 * @return true, if is ignore zero height
-	 */
-	public static boolean isIgnoreZeroHeight() {
-		return ignoreZeroHeight;
-	}
-
-	/**
-	 * Sets the ignore zero height.
-	 *
-	 * @param ignoreZeroHeight the new ignore zero height
-	 */
-	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) {
-		if (this.wayPoints != wayPoints) {
-			this.wayPoints = new ArrayList<WayPoint>(wayPoints);
-			numWayPoints = wayPoints != null ? wayPoints.size() : 0;
-			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()));
-		}
-	}
-
-	/*
-	 * (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 List<IElevationProfile> getChildren() {
-	    return null;
-	}
-
-	/*
-	 * (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 the coordinate bounds of this profile. See {@link Bounds} for details.
-	 *
-	 * @return the bounds of this elevation profile
-	 */
-	public Bounds getBounds() {
-	    return bounds;
-	}
-
-	/**
-	 * 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);
-		}
-
-		// update boundaries
-		if (bounds == null) {
-		    bounds = new Bounds(wp.getCoor());
-		} else {
-		    bounds.extend(wp.getCoor());
-		}
-		
-		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 name; /*"ElevationProfileBase [start=" + getStart() + ", end=" + getEnd()
-				+ ", minHeight=" + getMinHeight() + ", maxHeight="
-				+ getMaxHeight() + "]";*/
-	}
-}
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 29961)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/GpxIterator.java	(revision 29962)
@@ -48,7 +48,7 @@
 		if (data.isEmpty()) return;
 		
-		visitor.start();
+		visitor.beginWayPoints();
 		visitSingleWaypoints(data, visitor);
-		visitor.end();
+		visitor.endWayPoints();
 
 		// routes
@@ -98,5 +98,5 @@
 		
 		if (segments != null) {
-		    	visitor.start(trk);
+		    	visitor.beginTrack(trk);
 		    	// visit all segments
 			for (GpxTrackSegment segment : segments) {
@@ -106,13 +106,13 @@
 					continue;
 				
-			        visitor.start(trk, segment);
+			        visitor.beginTrackSegment(trk, segment);
 			        
 				for (WayPoint wayPoint : waypts) {
-					visitor.visit(wayPoint);
+					visitor.visitTrackPoint(wayPoint, trk, segment);
 				}
 				
-				visitor.end(trk, segment);
+				visitor.endTrackSegment(trk, segment);
 			}
-			visitor.end(trk);
+			visitor.endTrack(trk);
 		}		
 		
@@ -127,9 +127,9 @@
 		if (visitor == null) return;
 		
-		visitor.start();
+		visitor.beginWayPoints();
 		for (WayPoint wpt : route.routePoints) {
-			visitor.visit(wpt);
+			visitor.visitRoutePoint(wpt, route);
 		}
-		visitor.end();
+		visitor.endWayPoints();
 	}
 
@@ -142,5 +142,5 @@
 		if (data.waypoints != null) { // better with an hasWaypoints method!?
 			for (WayPoint wpt : data.waypoints) {
-				visitor.visit(wpt);
+				visitor.visitWayPoint(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 29961)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxVisitor.java	(revision 29962)
@@ -15,4 +15,5 @@
 package org.openstreetmap.josm.plugins.elevation.gpx;
 
+import org.openstreetmap.josm.data.gpx.GpxRoute;
 import org.openstreetmap.josm.data.gpx.GpxTrack;
 import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
@@ -25,22 +26,32 @@
 public interface IGpxVisitor extends IGpxWaypointVisitor {
 	/**
-	 * Starts a GPX route or way point collection.
+	 * Starts a GPX way point collection.
 	 */
-	void start();
+	void beginWayPoints();
 	
 	/**
-	 * Ends a GPX route or way point collection.
+	 * Ends a GPX way point collection.
 	 */
-	void end();
+	void endWayPoints();
 	
 	/**
 	 * Starts a GPX track.
 	 */
-	void start(GpxTrack track);
+	void beginTrack(GpxTrack track);
 	
 	/**
 	 * Ends a GPX track.
 	 */
-	void end(GpxTrack track);
+	void endTrack(GpxTrack track);
+	
+	/**
+	 * Starts a GPX route.
+	 */
+	void beginRoute(GpxRoute track);
+	
+	/**
+	 * Ends a GPX route.
+	 */
+	void endRoute(GpxRoute track);
 
 	
@@ -48,10 +59,10 @@
 	 * Starts a segment within a GPX track.
 	 */
-	void start(GpxTrack track, GpxTrackSegment segment);
+	void beginTrackSegment(GpxTrack track, GpxTrackSegment segment);
 	
 	/**
 	 * Ends a segment within a GPX track.
 	 */
-	void end(GpxTrack track, GpxTrackSegment segment);
+	void endTrackSegment(GpxTrack track, GpxTrackSegment segment);
 	
 	/**
@@ -60,4 +71,20 @@
 	 * @param wp The way point to visit.
 	 */
-	void visit(WayPoint wp);
+	void visitWayPoint(WayPoint wp);
+	
+	/**
+	 * Visits a way point within a GPX track.
+	 *
+	 * @param wp The way point to visit.
+	 * @param track the track containing the way point.
+	 * @param segment the track segment
+	 */
+	void visitTrackPoint(WayPoint wp, GpxTrack track, GpxTrackSegment segment);
+	
+	/**
+	 * Visits a way point within a GPX route.
+	 * @param route the route containing the way point.
+	 * @param wp the way point to visit.
+	 */
+	void visitRoutePoint(WayPoint wp, GpxRoute route);
 }
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 29961)
+++ applications/editors/josm/plugins/ElevationProfile/src/org/openstreetmap/josm/plugins/elevation/gpx/IGpxWaypointVisitor.java	(revision 29962)
@@ -27,4 +27,4 @@
 	 * @param wp The way point to visit.
 	 */
-	void visit(WayPoint wp);
+	void visitWayPoint(WayPoint wp);
 }
