Index: src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java
===================================================================
--- src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(revision 714)
+++ src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(working copy)
@@ -7,6 +7,8 @@
 import java.awt.event.ActionListener;
 
 import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.tools.GBC;
@@ -14,11 +16,13 @@
 public class DrawingPreference implements PreferenceSetting {
 
 	private JCheckBox drawRawGpsLines = new JCheckBox(tr("Draw lines between raw gps points."));
+	private JTextField drawRawGpsMaxLineLength = new JTextField(8);
 	private JCheckBox forceRawGpsLines = new JCheckBox(tr("Force lines if no segments imported."));
 	private JCheckBox largeGpsPoints = new JCheckBox(tr("Draw large GPS points."));
 	private JCheckBox colorTracks = new JCheckBox(tr("Color tracks by velocity."));
 	private JCheckBox directionHint = new JCheckBox(tr("Draw Direction Arrows"));
 	private JCheckBox drawGpsArrows = new JCheckBox(tr("Draw Direction Arrows"));
+	private JCheckBox drawGpsArrowsFast = new JCheckBox(tr("Fast drawing (looks uglier)"));
 	private JCheckBox interestingDirections = new JCheckBox(tr("Only interesting direction hints (e.g. with oneway tag)."));
 	private JCheckBox segmentOrderNumber = new JCheckBox(tr("Draw segment order numbers"));
 	private JCheckBox sourceBounds = new JCheckBox(tr("Draw boundaries of downloaded data"));
@@ -28,12 +32,10 @@
 		// drawRawGpsLines
 		drawRawGpsLines.addActionListener(new ActionListener(){
 			public void actionPerformed(ActionEvent e) {
-                            if (!drawRawGpsLines.isSelected()){
-                                forceRawGpsLines.setSelected(false);
-                                drawGpsArrows.setSelected(false);
-                            }
                             forceRawGpsLines.setEnabled(drawRawGpsLines.isSelected());
+                            drawRawGpsMaxLineLength.setEnabled(drawRawGpsLines.isSelected());
                             drawGpsArrows.setEnabled(drawRawGpsLines.isSelected());
+                            drawGpsArrowsFast.setEnabled(drawGpsArrows.isSelected() && drawGpsArrows.isEnabled());
                             colorTracks.setEnabled(drawRawGpsLines.isSelected());
 			}
 		});
@@ -41,6 +43,13 @@
 		drawRawGpsLines.setToolTipText(tr("If your gps device draw too few lines, select this to draw lines along your way."));
 		gui.display.add(drawRawGpsLines, GBC.eol().insets(20,0,0,0));
 
+		// drawRawGpsMaxLineLength
+		drawRawGpsMaxLineLength.setText(Main.pref.get("draw.rawgps.max-line-length", "-1"));
+		drawRawGpsMaxLineLength.setToolTipText(tr("Maximum length (in meters) to draw lines. Set to '-1' to draw all lines."));
+		drawRawGpsMaxLineLength.setEnabled(drawRawGpsLines.isSelected());
+		gui.display.add(new JLabel(tr("Maximum length (meters)")), GBC.std().insets(40,0,0,0));
+		gui.display.add(drawRawGpsMaxLineLength, GBC.eol().fill(GBC.HORIZONTAL).insets(5,0,0,5));
+
 		// forceRawGpsLines
 		forceRawGpsLines.setToolTipText(tr("Force drawing of lines if the imported data contain no line information."));
 		forceRawGpsLines.setSelected(Main.pref.getBoolean("draw.rawgps.lines.force"));
@@ -48,11 +57,22 @@
 		gui.display.add(forceRawGpsLines, GBC.eop().insets(40,0,0,0));
 		
 		// drawGpsArrows
+		drawGpsArrows.addActionListener(new ActionListener(){
+			public void actionPerformed(ActionEvent e) {
+                            drawGpsArrowsFast.setEnabled(drawGpsArrows.isSelected() && drawGpsArrows.isEnabled());
+			}
+		});
 		drawGpsArrows.setToolTipText(tr("Draw direction arrows for lines, connecting GPS points."));
 		drawGpsArrows.setSelected(Main.pref.getBoolean("draw.rawgps.direction"));
 		drawGpsArrows.setEnabled(drawRawGpsLines.isSelected());
 		gui.display.add(drawGpsArrows, GBC.eop().insets(40,0,0,0));
 
+		// drawGpsArrowsFast
+		drawGpsArrowsFast.setToolTipText(tr("Draw the direction arrows using table lookups instead of complex math."));
+		drawGpsArrowsFast.setSelected(Main.pref.getBoolean("draw.rawgps.alternatedirection"));
+		drawGpsArrowsFast.setEnabled(drawGpsArrows.isSelected() && drawGpsArrows.isEnabled());
+		gui.display.add(drawGpsArrowsFast, GBC.eop().insets(60,0,0,0));
+
 		// colorTracks
 		colorTracks.setSelected(Main.pref.getBoolean("draw.rawgps.colors"));
 		colorTracks.setToolTipText(tr("Choose the hue for the track color by the velocity at that point."));
@@ -75,7 +95,7 @@
                             interestingDirections.setEnabled(directionHint.isSelected());
 			}
 		});
-		directionHint.setToolTipText(tr("Draw direction hints for segments."));
+		directionHint.setToolTipText(tr("Draw direction hints for way segments."));
 		directionHint.setSelected(Main.pref.getBoolean("draw.segment.direction"));
 		gui.display.add(directionHint, GBC.eop().insets(20,0,0,0));
 
@@ -103,8 +123,10 @@
 
 	public void ok() {
 		Main.pref.put("draw.rawgps.lines", drawRawGpsLines.isSelected());
+		Main.pref.put("draw.rawgps.max-line-length", drawRawGpsMaxLineLength.getText());
 		Main.pref.put("draw.rawgps.lines.force", forceRawGpsLines.isSelected());
 		Main.pref.put("draw.rawgps.direction", drawGpsArrows.isSelected());
+		Main.pref.put("draw.rawgps.alternatedirection", drawGpsArrowsFast.isSelected());
 		Main.pref.put("draw.rawgps.colors", colorTracks.isSelected());
 		Main.pref.put("draw.rawgps.large", largeGpsPoints.isSelected());
 		Main.pref.put("draw.segment.direction", directionHint.isSelected());
Index: src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 714)
+++ src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(working copy)
@@ -76,7 +76,9 @@
 	private final GpxLayer me;
 	protected static final double PHI = Math.toRadians(15);
 	private boolean computeCacheInSync;
-	private int computeCacheMaxLineLingthUsed;
+	private int computeCacheMaxLineLengthUsed;
+	private Color computeCacheColorUsed;
+	private boolean computeCacheColored;
 	
 	public GpxLayer(GpxData d) {
 		super((String) d.attr.get("name"));
@@ -351,6 +353,11 @@
 	};
 
 	@Override public void paint(Graphics g, MapView mv) {
+
+		/****************************************************************
+		 ********** STEP 1 - GET CONFIG VALUES **************************
+		 ****************************************************************/
+		Long startTime = System.currentTimeMillis();
 		String gpsCol = Main.pref.get("color.gps point");
 		String gpsColSpecial = Main.pref.get("color.layer "+name);
 		Color neutralColor;
@@ -361,11 +368,14 @@
 		} else{
 			neutralColor = Color.GRAY;
 		}
-		g.setColor(neutralColor);
-		
 		boolean forceLines = Main.pref.getBoolean("draw.rawgps.lines.force");                     // also draw lines between points belonging to different segments
 		boolean direction = Main.pref.getBoolean("draw.rawgps.direction");                        // draw direction arrows on the lines
-		int maxLineLength = Integer.parseInt(Main.pref.get("draw.rawgps.max-line-length", "-1")); // don't draw lines if longer than x meters
+		int maxLineLength = -1;
+		try {
+			maxLineLength = Integer.parseInt(Main.pref.get("draw.rawgps.max-line-length", "-1"));   // don't draw lines if longer than x meters
+		} catch (java.lang.NumberFormatException e) {
+			Main.pref.put("draw.rawgps.max-line-length", "-1");
+		}
 		boolean lines = Main.pref.getBoolean("draw.rawgps.lines");                                // draw line between points, global setting
 		String linesKey = "draw.rawgps.lines.layer "+name;
 		if (Main.pref.hasKey(linesKey))
@@ -373,14 +383,24 @@
 		boolean large = Main.pref.getBoolean("draw.rawgps.large");                                // paint large dots for points
 		boolean colored = Main.pref.getBoolean("draw.rawgps.colors");                             // color the lines
 		boolean alternatedirection = Main.pref.getBoolean("draw.rawgps.alternatedirection");      // paint direction arrow with alternate math. may be faster
-		boolean trianglelines = Main.pref.getBoolean("draw.rawgps.trianglelines");                // paint lines as 2 lines
 
-		if (computeCacheInSync && computeCacheMaxLineLingthUsed != maxLineLength) {
+		/****************************************************************
+		 ********** STEP 2a - CHECK CACHE VALIDITY **********************
+		 ****************************************************************/
+		if (computeCacheInSync && ((computeCacheMaxLineLengthUsed != maxLineLength) ||
+		                           (!neutralColor.equals(computeCacheColorUsed)) ||
+		                           (computeCacheColored != colored))) {
+			System.out.println("(re-)computing gpx line styles, reason: CCIS=" + computeCacheInSync + " CCMLLU=" + (computeCacheMaxLineLengthUsed != maxLineLength) + " CCCU=" +  (!neutralColor.equals(computeCacheColorUsed)) + " CCC=" + (computeCacheColored != colored));
+			computeCacheMaxLineLengthUsed = maxLineLength;
 			computeCacheInSync = false;
+			computeCacheColorUsed = neutralColor;
+			computeCacheColored = colored;
 		}
 
-		if (!computeCacheInSync && lines) { // don't compute if the cache is good or if there are no lines to draw at all
-			//System.out.println("(re-)computing gpx line styles, reason: CCIS=" + computeCacheInSync + " L=" + lines);
+		/****************************************************************
+		 ********** STEP 2b - RE-COMPUTE CACHE DATA *********************
+		 ****************************************************************/
+		if (!computeCacheInSync) { // don't compute if the cache is good
 		WayPoint oldWp = null;
 		for (GpxTrack trk : data.tracks) {
 				if (!forceLines) { // don't draw lines between segments, unless forced to
@@ -396,7 +416,9 @@
 						double dtime = trkPnt.time - oldWp.time;
 						double vel = dist/dtime;
 
-							if (dtime <= 0 || vel < 0 || vel > 36) { // attn: bad case first
+							if (!colored) {
+								trkPnt.speedLineColor = neutralColor;
+							} else if (dtime <= 0 || vel < 0 || vel > 36) { // attn: bad case first
 								trkPnt.speedLineColor = colors[255];
 							} else {
 								trkPnt.speedLineColor = colors[(int) (7*vel)];
@@ -416,9 +438,12 @@
 				}
 			}
 			computeCacheInSync = true;
-			computeCacheMaxLineLingthUsed = maxLineLength;
 		}
 						
+		/****************************************************************
+		 ********** STEP 3a - DRAW LINES ********************************
+		 ****************************************************************/
+		if (lines) {
 		Point old = null;
 		for (GpxTrack trk : data.tracks) {
 			for (Collection<WayPoint> segment : trk.trackSegs) {
@@ -426,44 +451,125 @@
 					if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
 						continue;
 					Point screen = mv.getPoint(trkPnt.eastNorth);
-					if (lines && trkPnt.drawLine) {
-						if ((old.x != screen.x) || (old.y != screen.y)) { // skip points that are on the same screenposition
-							if (colored) {
+						if (trkPnt.drawLine) {
+							if (old != null && ((old.x != screen.x) || (old.y != screen.y))) { // skip points that are on the same screenposition
 								g.setColor(trkPnt.speedLineColor);
-							}
-							if (trianglelines) { // fast
-								g.drawLine(screen.x, screen.y, old.x + dir[trkPnt.dir][0], old.y + dir[trkPnt.dir][1]);
-								g.drawLine(screen.x, screen.y, old.x + dir[trkPnt.dir][2], old.y + dir[trkPnt.dir][3]);
-							} else { // slow
                                                 g.drawLine(old.x, old.y, screen.x, screen.y);
 							}
-                                                if (direction) {
-								if (alternatedirection) { // a little bit faster
-									g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][0], screen.y + dir[trkPnt.dir][1]);
-									g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][2], screen.y + dir[trkPnt.dir][3]);
-								} else { // a tiny bit slower, may not make a difference at all
+						}
+						old = screen;
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if lines
+
+		/****************************************************************
+		 ********** STEP 3b - DRAW NICE ARROWS **************************
+		 ****************************************************************/
+		if (lines && direction && !alternatedirection) {
+			Point old = null;
+			for (GpxTrack trk : data.tracks) {
+				for (Collection<WayPoint> segment : trk.trackSegs) {
+					for (WayPoint trkPnt : segment) {
+						if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
+							continue;
+						if (trkPnt.drawLine) {
+							Point screen = mv.getPoint(trkPnt.eastNorth);
+							if (old != null && ((old.x != screen.x) || (old.y != screen.y))) { // skip points that are on the same screenposition
+								g.setColor(trkPnt.speedLineColor);
                                                     double t = Math.atan2(screen.y-old.y, screen.x-old.x) + Math.PI;
                                                     g.drawLine(screen.x,screen.y, (int)(screen.x + 10*Math.cos(t-PHI)), (int)(screen.y + 10*Math.sin(t-PHI)));
                                                     g.drawLine(screen.x,screen.y, (int)(screen.x + 10*Math.cos(t+PHI)), (int)(screen.y + 10*Math.sin(t+PHI)));
                                                 }
+							old = screen;
 							}
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if lines
+
+		/****************************************************************
+		 ********** STEP 3c - DRAW FAST ARROWS **************************
+		 ****************************************************************/
+		if (lines && direction && alternatedirection) {
+			Point old = null;
+			for (GpxTrack trk : data.tracks) {
+				for (Collection<WayPoint> segment : trk.trackSegs) {
+					for (WayPoint trkPnt : segment) {
+						if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
+							continue;
+						if (trkPnt.drawLine) {
+							Point screen = mv.getPoint(trkPnt.eastNorth);
+							if (old != null && ((old.x != screen.x) || (old.y != screen.y))) { // skip points that are on the same screenposition
+								g.setColor(trkPnt.speedLineColor);
+								g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][0], screen.y + dir[trkPnt.dir][1]);
+								g.drawLine(screen.x, screen.y, screen.x + dir[trkPnt.dir][2], screen.y + dir[trkPnt.dir][3]);
 						}
-                                            }else{
-						if (colored) { // reset color for non-line drawing if lines are variable colored
-							g.setColor(neutralColor);
+							old = screen;
                                             }
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if lines
+
+		/****************************************************************
+		 ********** STEP 3d - DRAW LARGE POINTS *************************
+		 ****************************************************************/
 						if (large) {
+			g.setColor(neutralColor);
+			for (GpxTrack trk : data.tracks) {
+				for (Collection<WayPoint> segment : trk.trackSegs) {
+					for (WayPoint trkPnt : segment) {
+						if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
+							continue;
+						Point screen = mv.getPoint(trkPnt.eastNorth);
 							g.fillRect(screen.x-1, screen.y-1, 3, 3);
-						} else {
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if large
+
+		/****************************************************************
+		 ********** STEP 3e - DRAW SMALL POINTS FOR LINES ***************
+		 ****************************************************************/
+		if (!large && lines){
+			g.setColor(neutralColor);
+			for (GpxTrack trk : data.tracks) {
+				for (Collection<WayPoint> segment : trk.trackSegs) {
+					for (WayPoint trkPnt : segment) {
+						if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
+							continue;
+						if (!trkPnt.drawLine) {
+							Point screen = mv.getPoint(trkPnt.eastNorth);
 						g.drawRect(screen.x, screen.y, 0, 0);
 					}
-					}
-					old = screen;
-				}
-			}
-		}
-	}
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if large
 
+		/****************************************************************
+		 ********** STEP 3f - DRAW SMALL POINTS INSTEAD OF LINES ********
+		 ****************************************************************/
+		if (!large && !lines){
+			g.setColor(neutralColor);
+			for (GpxTrack trk : data.tracks) {
+				for (Collection<WayPoint> segment : trk.trackSegs) {
+					for (WayPoint trkPnt : segment) {
+						if (Double.isNaN(trkPnt.latlon.lat()) || Double.isNaN(trkPnt.latlon.lon()))
+							continue;
+						Point screen = mv.getPoint(trkPnt.eastNorth);
+						g.drawRect(screen.x, screen.y, 0, 0);
+					} // end for trkpnt
+				} // end for segment
+			} // end for trk
+		} // end if large
+
+	Long duration = System.currentTimeMillis() - startTime;
+	//System.out.println(duration);
+
+	} // end paint
+
 	@Override public void visitBoundingBox(BoundingXYVisitor v) {
 		for (WayPoint p : data.waypoints)
 			v.visit(p.eastNorth);
