Index: applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RelationEditMode.java
===================================================================
--- applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RelationEditMode.java	(revision 21170)
+++ applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/RelationEditMode.java	(revision 21174)
@@ -62,6 +62,8 @@
 	@Override
 	public void mouseClicked(MouseEvent e) {
+		if (Main.main.getCurrentDataSet() == null)
+			return;
+
 		Way way = Main.map.mapView.getNearestWay(e.getPoint());
-
 		Collection<Relation> selectedRelations = Main.main.getCurrentDataSet().getSelectedRelations();
 
Index: applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/AbstractLinePainter.java
===================================================================
--- applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/AbstractLinePainter.java	(revision 21170)
+++ applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/AbstractLinePainter.java	(revision 21174)
@@ -1,13 +1,24 @@
 package org.openstreetmap.josm.plugins.routes.paint;
 
+import java.awt.Graphics2D;
+import java.awt.Point;
+import java.awt.Rectangle;
+import java.awt.geom.GeneralPath;
 import java.awt.geom.Line2D;
 import java.awt.geom.Point2D;
+import java.util.List;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.visitor.paint.LineClip;
+import org.openstreetmap.josm.gui.MapView;
+import org.openstreetmap.josm.gui.NavigatableComponent;
 
 public abstract class AbstractLinePainter implements PathPainter {
-	
+
 	// Following two method copied from http://blog.persistent.info/2004/03/java-lineline-intersections.html
 	protected boolean getLineLineIntersection(Line2D.Double l1,
 			Line2D.Double l2,
-			Point2D.Double intersection)
+			Point intersection)
 	{
 		double  x1 = l1.getX1(), y1 = l1.getY1(),
@@ -15,16 +26,23 @@
 		x3 = l2.getX1(), y3 = l2.getY1(),
 		x4 = l2.getX2(), y4 = l2.getY2();
-		
-		double ua = ((x4 - x3) * (y1 - y3) - (y4 - y3) * (x1 - x3)) / ((y4 - y3) * (x2 - x1) - (x4 - x3)*(y2 - y1));
-		intersection.x = x1 + ua * (x2 - x1);
-		intersection.y = y1 + ua * (y2 - y1);
-		 
+		double dx1 = x2 - x1;
+		double dx2 = x4 - x3;
+		double dy1 = y2 - y1;
+		double dy2 = y4 - y3;
 
-/*		intersection.x = det(det(x1, y1, x2, y2), x1 - x2,
-				det(x3, y3, x4, y4), x3 - x4)/
-				det(x1 - x2, y1 - y2, x3 - x4, y3 - y4);
-		intersection.y = det(det(x1, y1, x2, y2), y1 - y2,
-				det(x3, y3, x4, y4), y3 - y4)/
-				det(x1 - x2, y1 - y2, x3 - x4, y3 - y4);*/
+		double ua = (dx2 * (y1 - y3) - dy2 * (x1 - x3)) / (dy2 * dx1 - dx2 * dy1);
+
+		if (Math.abs(dy2 * dx1 - dx2 * dy1) < 0.0001) {
+			intersection.x = (int)l1.x2;
+			intersection.y = (int)l1.y2;
+			return false;
+		} else {
+			intersection.x = (int)(x1 + ua * (x2 - x1));
+			intersection.y = (int)(y1 + ua * (y2 - y1));
+		}
+
+		if (intersection.x > 600) {
+			System.out.println();
+		}
 
 		return true;
@@ -36,20 +54,20 @@
 	}
 
-	protected Point2D shiftPoint(Point2D p1, Point2D p2, double shift) {
+	protected Point shiftPoint(Point2D p1, Point2D p2, double shift) {
 		double dx = p2.getX() - p1.getX();
 		double dy = p2.getY() - p1.getY();
-		
+
 		// Perpendicular vector
 		double ndx = -dy;
 		double ndy = dx;
-		
+
 		// Normalize
 		double length = Math.sqrt(ndx * ndx + ndy * ndy);
 		ndx = ndx / length;
 		ndy = ndy / length;
-		
-		return new Point2D.Double(p1.getX() + shift * ndx, p1.getY() + shift * ndy);
+
+		return new Point((int)(p1.getX() + shift * ndx), (int)(p1.getY() + shift * ndy));
 	}
-	
+
 	protected Line2D.Double shiftLine(Point2D p1, Point2D p2, double shift) {
 		double dx = p2.getX() - p1.getX();
@@ -58,8 +76,110 @@
 		Point2D point1 = shiftPoint(p1, p2, shift);
 		Point2D point2 = new Point2D.Double(point1.getX() + dx, point1.getY() + dy);
-	
+
 		return new Line2D.Double(
 				point1, point2);
 	}
 
+	protected GeneralPath getPath(Graphics2D g, MapView mapView, List<Node> nodes, double shift) {
+
+		GeneralPath path = new GeneralPath();
+
+		if (nodes.size() < 2) {
+			return path;
+		}
+
+		Point p1 = null;
+		Point p2 = null;
+		Point p3 = null;
+		Point lastPoint = null;
+
+		for (Node n: nodes) {
+			Point p = mapView.getPoint(n);
+
+			if (!p.equals(p3)) {
+				p1 = p2;
+				p2 = p3;
+				p3 = p;
+			} else {
+				continue;
+			}
+
+			p = null;
+			if (p2 != null) {
+				if (p1 == null) {
+					p = shiftPoint(p2, p3, shift);
+				} else {
+					Line2D.Double line1 = shiftLine(p1, p2, shift);
+					Line2D.Double line2 = shiftLine(p2, p3, shift);
+
+					/*path.moveTo((float)line1.x1, (float)line1.y1);
+					path.lineTo((float)line1.x2, (float)line1.y2);
+					path.moveTo((float)line2.x1, (float)line2.y1);
+					path.lineTo((float)line2.x2, (float)line2.y2);*/
+
+					p = new Point();
+					if (!getLineLineIntersection(line1, line2, p)) {
+						p = null;
+					} else {
+						int dx = p.x - p2.x;
+						int dy = p.y - p2.y;
+						int distance = (int)Math.sqrt(dx * dx + dy * dy);
+						if (distance > 10) {
+							p.x = p2.x + dx / (distance / 10);
+							p.y = p2.y + dy / (distance / 10);
+						}
+					}
+				}
+			}
+
+			if (p != null && lastPoint != null) {
+				drawSegment(g, mapView, path, lastPoint, p);
+			}
+			if (p != null) {
+				lastPoint = p;
+			}
+		}
+
+		if (p2 != null && p3 != null && lastPoint != null) {
+			p3 = shiftPoint(p3, p2, -shift);
+			drawSegment(g, mapView, path, lastPoint, p3);
+		}
+
+		return path;
+	}
+
+	private void drawSegment(Graphics2D g, NavigatableComponent nc, GeneralPath path, Point p1, Point p2) {
+		boolean drawIt = false;
+		if (Main.isOpenjdk) {
+			/**
+			 * Work around openjdk bug. It leads to drawing artefacts when zooming in a lot. (#4289, #4424)
+			 * (It looks like int overflow when clipping.) We do custom clipping.
+			 */
+			Rectangle bounds = g.getClipBounds();
+			bounds.grow(100, 100);                  // avoid arrow heads at the border
+			LineClip clip = new LineClip();
+			drawIt = clip.cohenSutherland(p1.x, p1.y, p2.x, p2.y, bounds.x, bounds.y, bounds.x+bounds.width, bounds.y+bounds.height);
+			if (drawIt) {
+				p1 = clip.getP1();
+				p2 = clip.getP2();
+			}
+		} else {
+			drawIt = isSegmentVisible(nc, p1, p2);
+		}
+		if (drawIt) {
+			/* draw segment line */
+			path.moveTo(p1.x, p1.y);
+			path.lineTo(p2.x, p2.y);
+		}
+	}
+
+	private boolean isSegmentVisible(NavigatableComponent nc, Point p1, Point p2) {
+		if ((p1.x < 0) && (p2.x < 0)) return false;
+		if ((p1.y < 0) && (p2.y < 0)) return false;
+		if ((p1.x > nc.getWidth()) && (p2.x > nc.getWidth())) return false;
+		if ((p1.y > nc.getHeight()) && (p2.y > nc.getHeight())) return false;
+		return true;
+	}
+
+
 }
Index: applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/NarrowLinePainter.java
===================================================================
--- applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/NarrowLinePainter.java	(revision 21170)
+++ applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/NarrowLinePainter.java	(revision 21174)
@@ -3,8 +3,4 @@
 import java.awt.BasicStroke;
 import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
 import java.util.BitSet;
 import java.util.List;
@@ -17,8 +13,8 @@
 
 public class NarrowLinePainter extends AbstractLinePainter {
-	
+
 	private static final float LINE_WIDTH = 5;
 	private final RouteLayer layer;
-	
+
 	public NarrowLinePainter(RouteLayer layer) {
 		this.layer = layer;
@@ -28,9 +24,9 @@
 		List<Node> nodes = way.getNodes();
 		BitSet routes = way.getRoutes();
-		
+
 		if (nodes.size() < 2) {
 			return;
 		}
-		
+
 		//double totalWidth = LINE_WIDTH + (colors.size() - 1) * 4;
 		//double width = totalWidth / colors.size();
@@ -38,40 +34,18 @@
 		double width = LINE_WIDTH;
 		double shift = - (LINE_WIDTH * routes.cardinality()) / 2 + width / 2;
-		
+
 		for (int k=0; k<routes.length(); k++) {
-			
+
 			if (!routes.get(k)) {
 				continue;
 			}
-			
+
 			RouteDefinition route = layer.getRoutes().get(k);
-			
+
 			g.setColor(route.getColor());
 			g.setStroke(new BasicStroke((float) width));
-			
-			GeneralPath path = new GeneralPath();
-			Point2D start = shiftPoint(mapView.getPoint(nodes.get(0).getEastNorth()), 
-					mapView.getPoint(nodes.get(1).getEastNorth()), shift);
-			path.moveTo((float)start.getX(), (float)start.getY());
-			for (int i=1; i<nodes.size() - 1; i++) {
-				Point p1 = mapView.getPoint(nodes.get(i - 1).getEastNorth());
-				Point p2 = mapView.getPoint(nodes.get(i).getEastNorth());
-				Point p3 = mapView.getPoint(nodes.get(i + 1).getEastNorth());
 
+			g.draw(getPath(g, mapView, nodes, shift));
 
-				Line2D.Double line1 = shiftLine(p1, p2, shift);
-				Line2D.Double line2 = shiftLine(p2, p3, shift);
-
-				Point2D.Double intersection = new Point2D.Double();
-				getLineLineIntersection(line1, line2, intersection);
-				if (!Double.isNaN(intersection.getX())  && !Double.isNaN(intersection.getY())) {
-					path.lineTo((float)intersection.getX(), (float)intersection.getY());
-				}
-			}
-			Point2D stop = shiftPoint(mapView.getPoint(nodes.get(nodes.size() - 1).getEastNorth()), 
-					mapView.getPoint(nodes.get(nodes.size() - 2).getEastNorth()), -shift);
-			path.lineTo((float)stop.getX(), (float)stop.getY());
-			g.draw(path);
-			
 			shift += width + 2;
 		}
Index: applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/WideLinePainter.java
===================================================================
--- applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/WideLinePainter.java	(revision 21170)
+++ applications/editors/josm/plugins/routes/src/org/openstreetmap/josm/plugins/routes/paint/WideLinePainter.java	(revision 21174)
@@ -4,8 +4,4 @@
 import java.awt.Color;
 import java.awt.Graphics2D;
-import java.awt.Point;
-import java.awt.geom.GeneralPath;
-import java.awt.geom.Line2D;
-import java.awt.geom.Point2D;
 import java.util.BitSet;
 import java.util.List;
@@ -18,8 +14,8 @@
 
 public class WideLinePainter extends AbstractLinePainter {
-	
+
 	private static final float LINE_WIDTH = 10;
 	private final RouteLayer layer;
-	
+
 	public WideLinePainter(RouteLayer layer) {
 		this.layer = layer;
@@ -29,49 +25,27 @@
 		List<Node> nodes = way.getNodes();
 		BitSet routes = way.getRoutes();
-		
+
 		if (nodes.size() < 2) {
 			return;
 		}
-		
+
 		double totalWidth = LINE_WIDTH + (routes.size() - 1) * 4;
 		double width = totalWidth / routes.cardinality();
 		double shift = -totalWidth / 2 + width / 2;
-		
+
 		for (int k=0; k<routes.length(); k++) {
-			
+
 			if (!routes.get(k)) {
 				continue;
 			}
-			
+
 			RouteDefinition route = layer.getRoutes().get(k);
-	
+
 			Color color = route.getColor();
 			g.setColor(new Color(color.getRed(), color.getGreen(), color.getBlue(), 100));
 			g.setStroke(new BasicStroke((float) width));
-			
-			GeneralPath path = new GeneralPath();
-			Point2D start = shiftPoint(mapView.getPoint(nodes.get(0).getEastNorth()), 
-					mapView.getPoint(nodes.get(1).getEastNorth()), shift);
-			path.moveTo((float)start.getX(), (float)start.getY());
-			for (int i=1; i<nodes.size() - 1; i++) {
-				Point p1 = mapView.getPoint(nodes.get(i - 1).getEastNorth());
-				Point p2 = mapView.getPoint(nodes.get(i).getEastNorth());
-				Point p3 = mapView.getPoint(nodes.get(i + 1).getEastNorth());
 
+			g.draw(getPath(g, mapView, nodes, shift));
 
-				Line2D.Double line1 = shiftLine(p1, p2, shift);
-				Line2D.Double line2 = shiftLine(p2, p3, shift);
-
-				Point2D.Double intersection = new Point2D.Double();
-				getLineLineIntersection(line1, line2, intersection);
-				if (!Double.isNaN(intersection.getX())  && !Double.isNaN(intersection.getY())) {
-					path.lineTo((float)intersection.getX(), (float)intersection.getY());
-				}
-			}
-			Point2D stop = shiftPoint(mapView.getPoint(nodes.get(nodes.size() - 1).getEastNorth()), 
-					mapView.getPoint(nodes.get(nodes.size() - 2).getEastNorth()), -shift);
-			path.lineTo((float)stop.getX(), (float)stop.getY());
-			g.draw(path);
-			
 			shift += width;
 		}
