Index: /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 720)
+++ /trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java	(revision 721)
@@ -77,5 +77,7 @@
 	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) {
@@ -352,4 +354,9 @@
 
 	@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);
@@ -362,9 +369,12 @@
 			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;
@@ -374,12 +384,22 @@
 		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;
-		}
-
-		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);
+			computeCacheColorUsed = neutralColor;
+			computeCacheColored = colored;
+		}
+
+		/****************************************************************
+		 ********** STEP 2b - RE-COMPUTE CACHE DATA *********************
+		 ****************************************************************/
+		if (!computeCacheInSync) { // don't compute if the cache is good
 		WayPoint oldWp = null;
 		for (GpxTrack trk : data.tracks) {
@@ -397,5 +417,7 @@
 						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 {
@@ -417,7 +439,10 @@
 			}
 			computeCacheInSync = true;
-			computeCacheMaxLineLingthUsed = maxLineLength;
 		}
 						
+		/****************************************************************
+		 ********** STEP 3a - DRAW LINES ********************************
+		 ****************************************************************/
+		if (lines) {
 		Point old = null;
 		for (GpxTrack trk : data.tracks) {
@@ -427,41 +452,122 @@
 						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) {
Index: /trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java
===================================================================
--- /trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(revision 720)
+++ /trunk/src/org/openstreetmap/josm/gui/preferences/DrawingPreference.java	(revision 721)
@@ -8,4 +8,6 @@
 
 import javax.swing.JCheckBox;
+import javax.swing.JLabel;
+import javax.swing.JTextField;
 
 import org.openstreetmap.josm.Main;
@@ -15,4 +17,5 @@
 
 	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."));
@@ -20,4 +23,5 @@
 	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"));
@@ -29,10 +33,8 @@
 		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,4 +43,11 @@
 		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
@@ -49,8 +58,19 @@
 		
 		// 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
@@ -76,5 +96,5 @@
 			}
 		});
-		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));
@@ -104,6 +124,8 @@
 	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());
