Index: /trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 6205)
+++ /trunk/src/org/openstreetmap/josm/data/gpx/GpxData.java	(revision 6206)
@@ -5,4 +5,5 @@
 import java.io.File;
 import java.util.Collection;
+import java.util.Iterator;
 import java.util.LinkedList;
 import java.util.Map;
@@ -238,3 +239,86 @@
         return best;
     }
+
+    /**
+     * Iterate over all track segments and over all routes.
+     *
+     * @param trackVisibility An array indicating which tracks should be
+     * included in the iteration. Can be null, then all tracks are included.
+     * @return an Iterable object, which iterates over all track segments and
+     * over all routes
+     */
+    public Iterable<Collection<WayPoint>> getLinesIterable(final boolean[] trackVisibility) {
+        return new Iterable<Collection<WayPoint>>() {
+            @Override
+            public Iterator<Collection<WayPoint>> iterator() {
+                return new LinesIterator(GpxData.this, trackVisibility);
+            }
+        };
+    }
+    
+    /**
+     * Iterates over all track segments and then over all routes.
+     */
+    public static class LinesIterator implements Iterator<Collection<WayPoint>> {
+
+        private Iterator<GpxTrack> itTracks;
+        private int idxTracks;
+        private Iterator<GpxTrackSegment> itTrackSegments;
+        private Iterator<GpxRoute> itRoutes;
+
+        private Collection<WayPoint> next;
+        private boolean[] trackVisibility;
+
+        public LinesIterator(GpxData data, boolean[] trackVisibility) {
+            itTracks = data.tracks.iterator();
+            idxTracks = -1;
+            itRoutes = data.routes.iterator();
+            this.trackVisibility = trackVisibility;
+            next = getNext();
+        }
+
+        @Override
+        public boolean hasNext() {
+            return next != null;
+        }
+
+        @Override
+        public Collection<WayPoint> next() {
+            Collection<WayPoint> current = next;
+            next = getNext();
+            return current;
+        }
+
+        private Collection<WayPoint> getNext() {
+            if (itTracks != null) {
+                if (itTrackSegments != null && itTrackSegments.hasNext()) {
+                    return itTrackSegments.next().getWayPoints();
+                } else {
+                    while (itTracks.hasNext()) {
+                        GpxTrack nxtTrack = itTracks.next();
+                        idxTracks++;
+                        if (trackVisibility != null && !trackVisibility[idxTracks])
+                            continue;
+                        itTrackSegments = nxtTrack.getSegments().iterator();
+                        if (itTrackSegments.hasNext()) {
+                            return itTrackSegments.next().getWayPoints();
+                        }
+                    }
+                    // if we get here, all the Tracks are finished; Continue with
+                    // Routes
+                    itTracks = null;
+                }
+            }
+            if (itRoutes.hasNext()) {
+                return itRoutes.next().routePoints;
+            }
+            return null;
+        }
+
+        @Override
+        public void remove() {
+            throw new UnsupportedOperationException();
+        }
+    }
+    
 }
Index: /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 6205)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 6206)
@@ -17,4 +17,5 @@
 import java.text.DateFormat;
 import java.util.ArrayList;
+import java.util.Collection;
 import java.util.Date;
 import java.util.LinkedList;
@@ -489,41 +490,37 @@
             if (colorModeDynamic) {
                 if (colored == colorModes.velocity) {
-                    for (GpxTrack trk : data.tracks) {
-                        for (GpxTrackSegment segment : trk.getSegments()) {
-                            if(!forceLines) {
-                                oldWp = null;
+                    for (Collection<WayPoint> segment : data.getLinesIterable(null)) {
+                        if(!forceLines) {
+                            oldWp = null;
+                        }
+                        for (WayPoint trkPnt : segment) {
+                            LatLon c = trkPnt.getCoor();
+                            if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
+                                continue;
                             }
-                            for (WayPoint trkPnt : segment.getWayPoints()) {
-                                LatLon c = trkPnt.getCoor();
-                                if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
-                                    continue;
+                            if (oldWp != null && trkPnt.time > oldWp.time) {
+                                double vel = c.greatCircleDistance(oldWp.getCoor())
+                                        / (trkPnt.time - oldWp.time);
+                                if(vel > maxval) {
+                                    maxval = vel;
                                 }
-                                if (oldWp != null && trkPnt.time > oldWp.time) {
-                                    double vel = c.greatCircleDistance(oldWp.getCoor())
-                                            / (trkPnt.time - oldWp.time);
-                                    if(vel > maxval) {
-                                        maxval = vel;
-                                    }
-                                    if(vel < minval) {
-                                        minval = vel;
-                                    }
+                                if(vel < minval) {
+                                    minval = vel;
                                 }
-                                oldWp = trkPnt;
                             }
+                            oldWp = trkPnt;
                         }
                     }
                 } else if (colored == colorModes.dilution) {
-                    for (GpxTrack trk : data.tracks) {
-                        for (GpxTrackSegment segment : trk.getSegments()) {
-                            for (WayPoint trkPnt : segment.getWayPoints()) {
-                                Object val = trkPnt.attr.get("hdop");
-                                if (val != null) {
-                                    double hdop = ((Float) val).doubleValue();
-                                    if(hdop > maxval) {
-                                        maxval = hdop;
-                                    }
-                                    if(hdop < minval) {
-                                        minval = hdop;
-                                    }
+                    for (Collection<WayPoint> segment : data.getLinesIterable(null)) {
+                        for (WayPoint trkPnt : segment) {
+                            Object val = trkPnt.attr.get("hdop");
+                            if (val != null) {
+                                double hdop = ((Float) val).doubleValue();
+                                if(hdop > maxval) {
+                                    maxval = hdop;
+                                }
+                                if(hdop < minval) {
+                                    minval = hdop;
                                 }
                             }
@@ -544,70 +541,68 @@
             }
 
-            for (GpxTrack trk : data.tracks) {
-                for (GpxTrackSegment segment : trk.getSegments()) {
-                    if (!forceLines) { // don't draw lines between segments, unless forced to
-                        oldWp = null;
-                    }
-                    for (WayPoint trkPnt : segment.getWayPoints()) {
-                        LatLon c = trkPnt.getCoor();
-                        if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
-                            continue;
+            for (Collection<WayPoint> segment : data.getLinesIterable(null)) {
+                if (!forceLines) { // don't draw lines between segments, unless forced to
+                    oldWp = null;
+                }
+                for (WayPoint trkPnt : segment) {
+                    LatLon c = trkPnt.getCoor();
+                    if (Double.isNaN(c.lat()) || Double.isNaN(c.lon())) {
+                        continue;
+                    }
+                    trkPnt.customColoring = neutralColor;
+                    if(colored == colorModes.dilution && trkPnt.attr.get("hdop") != null) {
+                        float hdop = ((Float) trkPnt.attr.get("hdop")).floatValue();
+                        int hdoplvl =(int) Math.round(colorModeDynamic ? ((hdop-minval)*255/(maxval-minval))
+                                : (hdop <= 0 ? 0 : hdop * hdopfactor));
+                        // High hdop is bad, but high values in colors are green.
+                        // Therefore inverse the logic
+                        int hdopcolor = 255 - (hdoplvl > 255 ? 255 : hdoplvl);
+                        trkPnt.customColoring = colors[hdopcolor];
+                    }
+                    if (oldWp != null) {
+                        double dist = c.greatCircleDistance(oldWp.getCoor());
+                        boolean noDraw=false;
+                        switch (colored) {
+                        case velocity:
+                            double dtime = trkPnt.time - oldWp.time;
+                            if(dtime > 0) {
+                                float vel = (float) (dist / dtime);
+                                int velColor =(int) Math.round(colorModeDynamic ? ((vel-minval)*255/(maxval-minval))
+                                        : (vel <= 0 ? 0 : vel / colorTracksTune * 255));
+                                trkPnt.customColoring = colors[Math.max(0, Math.min(velColor, 255))];
+                            } else {
+                                trkPnt.customColoring = colors[255];
+                            }
+                            break;
+                        case direction:
+                            double dirColor = oldWp.getCoor().heading(trkPnt.getCoor()) / (2.0 * Math.PI) * 256;
+                            // Bad case first
+                            if (dirColor != dirColor || dirColor < 0.0 || dirColor >= 256.0) {
+                                trkPnt.customColoring = colors_cyclic[0];
+                            } else {
+                                trkPnt.customColoring = colors_cyclic[(int) (dirColor)];
+                            }
+                            break;
+                        case time:
+                            double t=trkPnt.time;
+                            if (t>0 && t<=now){ // skip bad timestamps
+                                int tColor = (int) Math.round((t-minval)*255/(maxval-minval));
+                                trkPnt.customColoring = colors[tColor];
+                            } else {
+                                trkPnt.customColoring = neutralColor;
+                            }
+                            break;
                         }
-                        trkPnt.customColoring = neutralColor;
-                        if(colored == colorModes.dilution && trkPnt.attr.get("hdop") != null) {
-                            float hdop = ((Float) trkPnt.attr.get("hdop")).floatValue();
-                            int hdoplvl =(int) Math.round(colorModeDynamic ? ((hdop-minval)*255/(maxval-minval))
-                                    : (hdop <= 0 ? 0 : hdop * hdopfactor));
-                            // High hdop is bad, but high values in colors are green.
-                            // Therefore inverse the logic
-                            int hdopcolor = 255 - (hdoplvl > 255 ? 255 : hdoplvl);
-                            trkPnt.customColoring = colors[hdopcolor];
-                        }
-                        if (oldWp != null) {
-                            double dist = c.greatCircleDistance(oldWp.getCoor());
-                            boolean noDraw=false;
-                            switch (colored) {
-                            case velocity:
-                                double dtime = trkPnt.time - oldWp.time;
-                                if(dtime > 0) {
-                                    float vel = (float) (dist / dtime);
-                                    int velColor =(int) Math.round(colorModeDynamic ? ((vel-minval)*255/(maxval-minval))
-                                            : (vel <= 0 ? 0 : vel / colorTracksTune * 255));
-                                    trkPnt.customColoring = colors[Math.max(0, Math.min(velColor, 255))];
-                                } else {
-                                    trkPnt.customColoring = colors[255];
-                                }
-                                break;
-                            case direction:
-                                double dirColor = oldWp.getCoor().heading(trkPnt.getCoor()) / (2.0 * Math.PI) * 256;
-                                // Bad case first
-                                if (dirColor != dirColor || dirColor < 0.0 || dirColor >= 256.0) {
-                                    trkPnt.customColoring = colors_cyclic[0];
-                                } else {
-                                    trkPnt.customColoring = colors_cyclic[(int) (dirColor)];
-                                }
-                                break;
-                            case time:
-                                double t=trkPnt.time;
-                                if (t>0 && t<=now){ // skip bad timestamps
-                                    int tColor = (int) Math.round((t-minval)*255/(maxval-minval));
-                                    trkPnt.customColoring = colors[tColor];
-                                } else {
-                                    trkPnt.customColoring = neutralColor;
-                                }
-                                break;
-                            }
-
-                            if (!noDraw && (maxLineLength == -1 || dist <= maxLineLength)) {
-                                trkPnt.drawLine = true;
-                                trkPnt.dir = (int) oldWp.getCoor().heading(trkPnt.getCoor());
-                            } else {
-                                trkPnt.drawLine = false;
-                            }
-                        } else { // make sure we reset outdated data
+
+                        if (!noDraw && (maxLineLength == -1 || dist <= maxLineLength)) {
+                            trkPnt.drawLine = true;
+                            trkPnt.dir = (int) oldWp.getCoor().heading(trkPnt.getCoor());
+                        } else {
                             trkPnt.drawLine = false;
                         }
-                        oldWp = trkPnt;
-                    }
+                    } else { // make sure we reset outdated data
+                        trkPnt.drawLine = false;
+                    }
+                    oldWp = trkPnt;
                 }
             }
@@ -619,34 +614,28 @@
         int i = 0;
         ensureTrackVisibilityLength();
-        for (GpxTrack trk: data.tracks) {
-            // hide tracks that were de-selected in ChooseTrackVisibilityAction
-            if(!trackVisibility[i++]) {
-                continue;
-            }
-
-            for (GpxTrackSegment trkSeg: trk.getSegments()) {
-                for(WayPoint pt : trkSeg.getWayPoints())
+        for (Collection<WayPoint> segment : data.getLinesIterable(trackVisibility)) {
+
+            for(WayPoint pt : segment)
+            {
+                Bounds b = new Bounds(pt.getCoor());
+                // last should never be null when this is true!
+                if(pt.drawLine) {
+                    b.extend(last.getCoor());
+                }
+                if(b.intersects(box))
                 {
-                    Bounds b = new Bounds(pt.getCoor());
-                    // last should never be null when this is true!
-                    if(pt.drawLine) {
-                        b.extend(last.getCoor());
-                    }
-                    if(b.intersects(box))
-                    {
-                        if(last != null && (visibleSegments.isEmpty()
-                                || visibleSegments.getLast() != last)) {
-                            if(last.drawLine) {
-                                WayPoint l = new WayPoint(last);
-                                l.drawLine = false;
-                                visibleSegments.add(l);
-                            } else {
-                                visibleSegments.add(last);
-                            }
+                    if(last != null && (visibleSegments.isEmpty()
+                            || visibleSegments.getLast() != last)) {
+                        if(last.drawLine) {
+                            WayPoint l = new WayPoint(last);
+                            l.drawLine = false;
+                            visibleSegments.add(l);
+                        } else {
+                            visibleSegments.add(last);
                         }
-                        visibleSegments.add(pt);
-                    }
-                    last = pt;
-                }
+                    }
+                    visibleSegments.add(pt);
+                }
+                last = pt;
             }
         }
