Index: src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(revision 10871)
+++ src/org/openstreetmap/josm/data/osm/visitor/paint/StyledMapRenderer.java	(working copy)
@@ -108,7 +108,7 @@
         private MapViewPoint prev;
         /* 'prev0' is a point that has distance 'offset' from 'prev' and the
          * line from 'prev' to 'prev0' is perpendicular to the way segment from
-         * 'prev' to the next point.
+         * 'prev' to the current point.
          */
         private double xPrev0;
         private double yPrev0;
@@ -136,11 +136,13 @@
                 return current;
             }
 
+            double xCurrent = current.getInViewX();
+            double yCurrent = current.getInViewY();
             if (idx == nodes.size() - 1) {
                 ++idx;
                 if (prev != null) {
-                    return mapState.getForView(xPrev0 + current.getInViewX() - prev.getInViewX(),
-                                               yPrev0 + current.getInViewY() - prev.getInViewY());
+                    return mapState.getForView(xPrev0 + xCurrent - prev.getInViewX(),
+                                               yPrev0 + yCurrent - prev.getInViewY());
                 } else {
                     return current;
                 }
@@ -147,17 +149,18 @@
             }
 
             MapViewPoint next = getForIndex(idx + 1);
-
-            double dxNext = next.getInViewX() - current.getInViewX();
-            double dyNext = next.getInViewY() - current.getInViewY();
+            double dxNext = next.getInViewX() - xCurrent;
+            double dyNext = next.getInViewY() - yCurrent;
             double lenNext = Math.sqrt(dxNext*dxNext + dyNext*dyNext);
 
-            if (lenNext < 1e-3) {
+            if (lenNext < 1e-11) {
                 lenNext = 1; // value does not matter, because dy_next and dx_next is 0
             }
 
-            double xCurrent0 = current.getInViewX() + offset * dyNext / lenNext;
-            double yCurrent0 = current.getInViewY() - offset * dxNext / lenNext;
+            // calculate the position of the translated current point
+            double om = offset / lenNext;
+            double xCurrent0 = xCurrent + om * dyNext;
+            double yCurrent0 = yCurrent - om * dxNext;
 
             if (idx == 0) {
                 ++idx;
@@ -166,13 +169,13 @@
                 yPrev0 = yCurrent0;
                 return mapState.getForView(xCurrent0, yCurrent0);
             } else {
-                double dxPrev = current.getInViewX() - prev.getInViewX();
-                double dyPrev = current.getInViewY() - prev.getInViewY();
-
+                double dxPrev = xCurrent - prev.getInViewX();
+                double dyPrev = yCurrent - prev.getInViewY();
                 // determine intersection of the lines parallel to the two segments
                 double det = dxNext*dyPrev - dxPrev*dyNext;
+                double m = dxNext*(yCurrent0 - yPrev0) - dyNext*(xCurrent0 - xPrev0);
 
-                if (Utils.equalsEpsilon(det, 0)) {
+                if (Utils.equalsEpsilon(det, 0) || Math.signum(det) != Math.signum(m)) {
                     ++idx;
                     prev = current;
                     xPrev0 = xCurrent0;
@@ -180,10 +183,45 @@
                     return mapState.getForView(xCurrent0, yCurrent0);
                 }
 
-                double m = dxNext*(yCurrent0 - yPrev0) - dyNext*(xCurrent0 - xPrev0);
+                double f = m / det;
+                if (f < 0) {
+                    ++idx;
+                    prev = current;
+                    xPrev0 = xCurrent0;
+                    yPrev0 = yCurrent0;
+                    return mapState.getForView(xCurrent0, yCurrent0);
+                }
+                // the position of the intersection or intermittent point
+                double cx = xPrev0 + f * dxPrev;
+                double cy = yPrev0 + f * dyPrev;
 
-                double cx = xPrev0 + m * dxPrev / det;
-                double cy = yPrev0 + m * dyPrev / det;
+                if (f > 1) {
+                    // check if the intersection point is too far away, this will happen for sharp angles
+                    double dxI = cx - xCurrent;
+                    double dyI = cy - yCurrent;
+                    double lenISq = dxI * dxI + dyI * dyI;
+
+                    if (lenISq > Math.abs(2 * offset * offset)) {
+                        // intersection point is too far away, calculate intermittent points for capping
+                        double dxPrev0 = xCurrent0 - xPrev0;
+                        double dyPrev0 = yCurrent0 - yPrev0;
+                        double lenPrev0 = Math.sqrt(dxPrev0 * dxPrev0 + dyPrev0 * dyPrev0);
+                        f = 1 + Math.abs(offset / lenPrev0);
+                        double cxCap = xPrev0 + f * dxPrev;
+                        double cyCap = yPrev0 + f * dyPrev;
+                        xPrev0 = cxCap;
+                        yPrev0 = cyCap;
+                        // calculate a virtual prev point which lies on a line that goes through current and
+                        // is perpendicular to the line that goes through current and the intersection
+                        // so that the next capping point is calculated with it.
+                        double lenI = Math.sqrt(lenISq);
+                        double xv = xCurrent + dyI / lenI;
+                        double yv = yCurrent - dxI / lenI;
+
+                        prev = mapState.getForView(xv, yv);
+                        return mapState.getForView(cxCap, cyCap);
+                    }
+                }
                 ++idx;
                 prev = current;
                 xPrev0 = xCurrent0;
