Index: /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/DrawnPolyLine.java
===================================================================
--- /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/DrawnPolyLine.java	(revision 26101)
+++ /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/DrawnPolyLine.java	(revision 26101)
@@ -0,0 +1,284 @@
+package org.openstreetmap.josm.plugins.fastdraw;
+
+import java.awt.Point;
+import java.util.HashSet;
+import java.util.Iterator;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.ListIterator;
+import java.util.Set;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.gui.MapView;
+
+public class DrawnPolyLine {
+    MapView mv;
+    private LinkedList<LatLon> points = new LinkedList<LatLon>();
+    private LinkedList<LatLon> simplePoints = new LinkedList<LatLon>();
+    private Set<LatLon> used;
+    private Set<LatLon> fixed = new HashSet<LatLon>();
+    
+    private int lastIdx;
+
+    public void setMv(MapView mv) {
+        this.mv = mv;
+    }
+
+    boolean isFixed(LatLon pp2) {
+        return fixed.contains(pp2);
+    }
+
+    LinkedList<LatLon> getPoints() {
+        if (simplePoints!=null) return simplePoints; else return points;
+    }
+
+    boolean wasSimplified() {
+        return (simplePoints!=null && simplePoints.size()>0);
+    }
+    
+    int findClosestPoint(Point p, double d) {
+        double x=p.x, y=p.y;
+        int n=points.size();
+        int idx=-1;
+        double dist,minD=1e10;
+        for (int i=0;i<n;i++) {
+            dist = Math.sqrt(getPoint(points.get(i)).distanceSq(x,y));
+            if (dist<d && dist<minD) {
+                idx=i;
+                minD=dist;
+            };
+        }
+        return idx;
+    }
+
+    void clear() {
+        points.clear();
+        used=null;
+        lastIdx=0;
+        fixed.clear();
+        simplePoints=null;
+    }
+
+    void undo() {
+        //if (points.size() > 0) points.removeLast();
+        if (lastIdx>0 && lastIdx<points.size()){
+        points.remove(lastIdx);
+        lastIdx--;
+        }
+        
+    }
+    
+    void fixPoint(LatLon p) {
+        fixed.add(p);
+    }
+
+    void addFixed(LatLon coor) {
+         addLast(coor);
+        fixed.add(coor);
+    }
+    void addLast(LatLon coor) {
+        if (lastIdx>=points.size()-1) {
+            //System.out.println("add last "+points.size());
+            points.addLast(coor);if (points.size()>1) lastIdx++;
+            //System.out.println("lastIdx="+lastIdx);
+            }
+        else {points.add(lastIdx+1, coor); lastIdx++; 
+            //System.out.println("add at "+lastIdx+"/"+points.size());
+        }
+    }
+  
+    Point getLastPoint() {
+        return getPoint(points.get(lastIdx));
+    }
+
+    Point getPoint(LatLon p) {
+        return mv.getPoint(p);
+    }
+    
+    /**
+     * Simplified drawn line, not touching the nodes includes in "fixed" set.
+     */
+    void simplify(double epsilon) {
+        //System.out.println("Simplify polyline...");
+        int n = points.size();
+        if (n < 3) return;
+        used = new HashSet<LatLon>(n);
+        int start = 0;
+        for (int i = 0; i < n; i++) {
+            LatLon p = points.get(i);
+            if (fixed.contains(p) || i == n - 1) {
+                if (start < 0) {
+                    start = i;
+                } else {
+                    douglasPeucker(start, i, epsilon, 0);
+                }
+            }
+        }
+        simplePoints = new LinkedList<LatLon>();
+        simplePoints.addAll(points);
+        simplePoints.retainAll(used);
+        //Main.map.mapView.repaint();
+        used = null;
+    }
+
+    /**
+     * Simplification of the line specified by "points" field.
+     * Remainin points are included to "used" set.
+     * @param start - starting index
+     * @param end - ending index
+     * @param epsilon - min point-to line distance in pixels (tolerance)
+     * @param depth - recursion level
+     */
+    private void douglasPeucker(int start, int end, double epsilon, int depth) {
+        if (depth > 500) return;
+        if (end - start < 1) return; // incorrect invocation
+        LatLon first = points.get(start);
+        LatLon last = points.get(end);
+        Point firstp = getPoint(first);
+        Point lastp = getPoint(last);
+        used.add(first);
+        used.add(last);
+
+        if (end - start < 2) return;
+        
+        int farthest_node = -1;
+        double farthest_dist = 0;
+
+        double d = 0;
+
+        for (int i = start + 1; i < end; i++) {
+            d = pointLineDistance(getPoint(points.get(i)), firstp, lastp);
+            if (d > farthest_dist) {
+                farthest_dist = d;
+                farthest_node = i;
+            }
+        }
+
+        if (farthest_dist > epsilon) {
+            douglasPeucker(start, farthest_node, epsilon, depth + 1);
+            douglasPeucker(farthest_node, end, epsilon, depth + 1);
+        }
+    }
+
+    /** Modfified funclion from LakeWalker
+     * Gets distance from point p1 to line p2-p3
+     */
+    public double pointLineDistance(Point p1, Point p2, Point p3) {
+        double x0 = p1.x;        double y0 = p1.y;
+        double x1 = p2.x;        double y1 = p2.y;
+        double x2 = p3.x;        double y2 = p3.y;
+        if (x2 == x1 && y2 == y1) {
+            return Math.hypot(x1 - x0, y1 - y0);
+        } else {
+            return Math.abs((x2-x1)*(y1-y0)-(x1-x0)*(y2-y1))/Math.hypot(x2 - x1,y2 - y1);
+        }
+    }
+
+    void closeLine() {
+        points.add(points.getFirst());
+    }
+    
+    void deleteNode(int idx) {
+        if (idx<=lastIdx) lastIdx--;
+        fixed.remove(points.get(idx));
+        points.remove(idx); 
+    }
+    void tryToDeleteSegment(Point p) {
+        if (points.size()<3) return;
+        
+        LatLon start;
+        start = findBigSegment(p);
+        ListIterator<LatLon> it= points.listIterator();
+        LatLon pp;
+        boolean f=false;
+        int i=0,idx=-1;
+        while (it.hasNext()) {
+            pp=it.next();
+            if (f &&(fixed.contains(pp))) {
+                // if end of line fragment reached
+                lastIdx=idx;
+                return;
+            }if (f &&(!it.hasNext())) {
+                // if end of whole line reached
+                it.remove();
+                lastIdx=points.size()-1;
+                return;
+            }
+            
+            // if we are deleting this segment
+            if (f) it.remove(); 
+            if (pp == start) {f=true;idx=i;} // next node should be removed
+            i++;
+        }
+        lastIdx=points.size()-1;
+        }
+
+    /** find starting point of the polyline line fragment close to p
+     *  line fragment = segments between two fixed (green) nodes
+     * @param p
+     * @return 
+     */
+    LatLon findBigSegment(Point p) {
+        if (points.size()<2) return null;
+        Iterator<LatLon> it1 = points.listIterator(0);
+        Iterator<LatLon> it2 = points.listIterator(1);
+        Point p1,p2;
+        LatLon pp1,pp2,start=null;
+        start=points.getFirst();
+        do {
+        pp1=it1.next();
+        pp2=it2.next();
+        p1 = getPoint(pp1);
+        p2 = getPoint(pp2);
+        // maintain segment start end end
+        if (fixed.contains(pp1) ) { start=pp1; }
+        if (pointSegmentDistance(p,p1,p2) < 5) {
+            return start;
+        } 
+        } while (it2.hasNext());
+        return null;
+        
+    }
+
+    private double pointSegmentDistance(Point p, Point p1, Point p2) {
+        double a,b,x,y,l,h,kt,kn,dist;
+        x=p.x-p1.x; y=p.y-p1.y; 
+        a=p2.x-p1.x; b=p2.y-p1.y;
+        l=Math.hypot(a,b);
+        if (l==0) return Math.hypot(x, y); // p1 = p2
+        kt=(x*a+y*b)/l;
+        kn=Math.abs((-x*b+y*a)/l);
+        if (kt>=0 && kt<l) dist=kn; else {
+            dist=Math.min(Math.hypot(x, y), Math.hypot(x-a, y-b));
+        }
+        return dist;
+    }
+
+    void clearSimplifiedVersion() {
+        simplePoints=null;
+    }
+
+    boolean isLastPoint(int i) {
+        return (lastIdx==i);
+    }
+
+    void moveToTheEnd() {
+        lastIdx=points.size()-1;
+    }
+
+    void toggleFixed(int idx) {
+        LatLon p = points.get(idx);
+        if (fixed.contains(p)) fixed.remove(p);
+        else fixed.add(p);
+    }
+
+    
+
+   
+        
+        
+    
+
+    
+        
+}
Index: /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/FastDrawingMode.java
===================================================================
--- /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/FastDrawingMode.java	(revision 26100)
+++ /applications/editors/josm/plugins/turbopen/src/org/openstreetmap/josm/plugins/fastdraw/FastDrawingMode.java	(revision 26101)
@@ -15,5 +15,4 @@
 import java.awt.Point;
 import java.awt.event.MouseEvent;
-import java.awt.event.MouseWheelEvent;
 import org.openstreetmap.josm.data.coor.LatLon;
 import static org.openstreetmap.josm.tools.I18n.tr;
@@ -27,12 +26,9 @@
 import java.awt.event.InputEvent;
 import java.awt.event.KeyEvent;
-import java.awt.event.MouseWheelListener;
 import java.io.IOException;
 import java.util.*;
 import javax.swing.JOptionPane;
-import javax.swing.plaf.basic.BasicArrowButton;
 
 import org.openstreetmap.josm.Main;
-import org.openstreetmap.josm.actions.SimplifyWayAction;
 import org.openstreetmap.josm.actions.mapmode.MapMode;
 import org.openstreetmap.josm.command.AddCommand;
@@ -40,5 +36,4 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.Bounds;
-import org.openstreetmap.josm.data.osm.BBox;
 import org.openstreetmap.josm.data.osm.Node;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
@@ -49,5 +44,4 @@
 import org.openstreetmap.josm.gui.layer.MapViewPaintable;
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
-import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -59,4 +53,10 @@
     private static final String DRAWINGMODE_MESSAGE=
     "Click or Click&drag to continue, Ctrl-Click to add fixed node, Shift-Click to start new line";
+    
+    private static final Color COLOR_FIXED = Color.green;
+    private static final Color COLOR_NORMAL = Color.white;
+    private static final Color COLOR_DELETE = Color.red;
+    private static final Color COLOR_SELECTEDFRAGMENT = Color.red;
+    private static final Color COLOR_EDITEDFRAGMENT = Color.orange;
     
     private double maxDist;
@@ -68,7 +68,6 @@
     private double startingEps;
     
+    private DrawnPolyLine line;
     private MapView mv;
-    private ArrayList<LatLon> points = new ArrayList<LatLon>(100);
-    private ArrayList<LatLon> simplePoints = new ArrayList<LatLon>(100);
     private String statusText;
     private boolean drawing;
@@ -77,7 +76,5 @@
     private boolean oldCtrl;
     private boolean oldShift;
-    Set<LatLon> used;
-    Set<LatLon> fixed = new HashSet<LatLon>();
-    private double eps=startingEps;
+    private double eps;
     private final Stroke strokeForSimplified;
     private final Stroke strokeForOriginal;
@@ -89,4 +86,7 @@
     private final Cursor cursorNode;
     private boolean nearpoint;
+    private LatLon highlighted;
+    private int nearestIdx;
+    private Stroke strokeForDelete;
     
 
@@ -96,5 +96,7 @@
                 tr("Mode: {0}", tr("Fast drawing mode")),
                 KeyEvent.VK_T, Shortcut.GROUP_EDIT), mapFrame, Cursor.getPredefinedCursor(Cursor.DEFAULT_CURSOR));
+        line=new DrawnPolyLine();
         strokeForOriginal = new BasicStroke();
+        strokeForDelete = new BasicStroke(3);
         strokeForSimplified = new BasicStroke(1,BasicStroke.CAP_ROUND,BasicStroke.JOIN_BEVEL,5f,
                 new float[]{5.f,5f},0f);
@@ -107,4 +109,6 @@
     }
 
+// <editor-fold defaultstate="collapsed" desc="Event listeners">
+
     @Override
     public void enterMode() {
@@ -113,5 +117,6 @@
         loadPrefs();
         mv = Main.map.mapView;
-
+        line.setMv(mv);
+        
         if (getCurrentDataSet() == null) return;
         
@@ -144,5 +149,5 @@
         savePrefs();
         Main.map.mapView.setCursor(cursorDraw);
-        Main.map.mapView.repaint();
+        repaint();
     }
 
@@ -161,9 +166,9 @@
     @Override
     public void paint(Graphics2D g, MapView mv, Bounds bbox) {
-        if (points.size() == 0) return;
-        List<LatLon> pts=points;
-        if (simplePoints!=null && simplePoints.size()>0) {
+        LinkedList<LatLon> pts=line.getPoints();
+        if (pts.isEmpty()) return;
+        
+        if (line.wasSimplified()) {
             // we are drawing simplified version, that exists
-            pts=simplePoints;
             g.setStroke(strokeForSimplified);
         } else {
@@ -172,22 +177,45 @@
         
         Point p1, p2;
-        LatLon pp2;
-        p1 = getPoint(pts.get(0));
-        g.setColor(Color.green);
+        LatLon pp1, pp2;
+        p1 = line.getPoint(pts.get(0));
+        g.setColor(COLOR_FIXED);
         g.fillOval(p1.x - 3, p1.y - 3, 7, 7);
+        Color lineColor=COLOR_NORMAL;
         if (pts.size() > 1) {
+        Iterator<LatLon> it1,it2;
+        it1=pts.listIterator(0);
+        it2=pts.listIterator(1);
             for (int i = 0; i < pts.size() - 1; i++) {
-                g.setColor(Color.red);
-                p1 = getPoint(pts.get(i));
-                pp2 = pts.get(i + 1);
-                p2 = getPoint(pts.get(i + 1));
-
+                pp1 = it1.next();
+                p1 = line.getPoint(pp1);
+                pp2 = it2.next();
+                p2 = line.getPoint(pp2);
+                if (highlighted==pp1) {lineColor=COLOR_SELECTEDFRAGMENT;}
+                if (line.isLastPoint(i)) { lineColor=COLOR_EDITEDFRAGMENT; }
+                g.setColor(lineColor);
                 g.drawLine(p1.x, p1.y, p2.x, p2.y);
-                if (fixed.contains(pp2)) {
-                    g.setColor(Color.green);
+  //                  g.fillOval(p2.x - 5, p2.y - 5, 11, 11);
+                if (line.isFixed(pp2)) {
+                    lineColor=COLOR_NORMAL;
+                    g.setColor(COLOR_FIXED);
                     g.fillOval(p2.x - 3, p2.y - 3, 7, 7);
                 } else {
                     g.fillRect(p2.x - 1, p2.y - 1, 3, 3);
                 }
+                if (shift && !line.wasSimplified() && nearestIdx==i+1 ) {
+                    // highlight node to delete
+                    g.setStroke(strokeForDelete);
+                    g.setColor(COLOR_DELETE);
+                    g.drawLine(p2.x - 5, p2.y - 5,p2.x + 5, p2.y + 5);
+                    g.drawLine(p2.x - 5, p2.y + 5,p2.x + 5, p2.y - 5);
+                    g.setStroke(strokeForOriginal);
+                }
+                if (ctrl && !line.wasSimplified() && nearestIdx==i+1 ) {
+                    // highlight node to delete
+                    g.setStroke(strokeForDelete);
+                    g.setColor( line.isFixed(pp2) ? COLOR_NORMAL: COLOR_FIXED);
+                    g.drawOval(p2.x - 5, p2.y - 5, 11, 11);
+                    g.setStroke(strokeForOriginal);
+                }
             }
         }
@@ -206,5 +234,5 @@
         updateCursor();
 //        updateStatusLine();
-        Main.map.mapView.repaint();
+        repaint();
     }
 
@@ -214,8 +242,9 @@
         if (e.getButton() != MouseEvent.BUTTON1) return;
         
-        int idx = findClosestPoint(e.getX(),e.getY(),maxDist);
+        
+        int idx=line.findClosestPoint(e.getPoint(),maxDist);
         if (idx==0) {
+            line.closeLine();
             // the way should become closed
-            points.add(points.get(idx));
             drawing=false;
             ready=true;
@@ -224,32 +253,39 @@
         } 
         
-        if (shift) newDrawing();
-        if (ready) {
-            setStatusLine(tr(SIMPLIFYMODE_MESSAGE));
+        if (ctrl && shift) newDrawing();
+        if (!ctrl && shift) {
+            if (idx>=0) {line.deleteNode(idx); nearestIdx=-1;}
+            else line.tryToDeleteSegment(e.getPoint()); 
             return;
         }
+        if (idx>=0) {
+            if (ctrl) {
+                // toggle fixed point
+                line.toggleFixed(idx);                
+            }
+            return;
+        }
+        
+        if (ready) { setStatusLine(tr(SIMPLIFYMODE_MESSAGE)); return;  }
+        drawing = true;
         
         LatLon p = getLatLon(e);
         Node nd1 = getNearestNode(e.getPoint(), maxDist);
-
         if (nd1!=null) {
             // found node, make it fixed point of the line
             //System.out.println("node "+nd1);
             p=nd1.getCoor();
-            fixed.add(p);
+            line.fixPoint(p);
         }         
         
-        drawing = true;
-        points.add(p);
-        if (ctrl) fixed.add(p);
-        simplePoints=null;
+        line.addLast(p);
+        if (ctrl) line.fixPoint(p);
+        line.clearSimplifiedVersion();
                
         setStatusLine(tr("Please move the mouse to draw new way"));
-        Main.map.mapView.repaint();
-
-    }
-    
-    
-
+        repaint();
+
+    }
+ 
     @Override
     public void mouseReleased(MouseEvent e) {
@@ -259,5 +295,5 @@
         if (!ready) setStatusLine(tr(DRAWINGMODE_MESSAGE)
                         + tr(SIMPLIFYMODE_MESSAGE));
-        Main.map.mapView.repaint();
+        repaint();
     }
 
@@ -274,21 +310,33 @@
         if (nearpoint!=nearpoint2) {nearpoint=nearpoint2;updateCursor();}
         
-        if (!drawing) return;
-        if (ready) {
-            setStatusLine(tr(SIMPLIFYMODE_MESSAGE));
-        }
-        
-        Point lastP = getPoint(points.get(points.size() - 1));
-
+        nearestIdx=line.findClosestPoint(e.getPoint(),maxDist);
+        
+        if (!drawing) {
+            if (shift) {
+                // find line fragment to highlight
+                LatLon h2=line.findBigSegment(e.getPoint());
+                if (highlighted!=h2) {
+                    highlighted=h2;
+                    repaint();
+                } 
+            }
+            return;
+        }
+        if (ready) setStatusLine(tr(SIMPLIFYMODE_MESSAGE));
+        
+        // do not draw points close to existing points - we do not want self-intersections
+        if (nearestIdx>=0) { return; }
+        
+        Point lastP = line.getLastPoint(); // last point of line fragment being edited
+                
         if (nearpoint){
             if ( Math.hypot(e.getX() - lastP.x, e.getY() - lastP.y) > 1e-2) {
-                points.add(nd1.getCoor());
-                fixed.add(nd1.getCoor());
-                Main.map.mapView.repaint();
+                line.addFixed(nd1.getCoor()); // snap to node coords
+                repaint();
             } 
         } else {
             if (Math.hypot(e.getX() - lastP.x, e.getY() - lastP.y) > minPixelsBetweenPoints) {
-                points.add(getLatLon(e));
-                Main.map.mapView.repaint();
+                line.addLast(getLatLon(e)); // free mouse-drawing
+                repaint();
             }
         }
@@ -297,34 +345,38 @@
     }
 
-    @Override
-    protected void updateStatusLine() {
-        Main.map.statusLine.setHelpText(statusText);
-        Main.map.statusLine.repaint();
-
-    }
-
-    LatLon getLatLon(MouseEvent e) {
-        return mv.getLatLon(e.getX(), e.getY());
-    }
-
-    Point getPoint(LatLon p) {
-        return mv.getPoint(p);
-    }
-
-    public void newDrawing() {
-        points.clear();
-        used=null;
-        fixed.clear();
-        eps=startingEps;
-        ready=false;
-        simplePoints=null;
-    }
-
-    public void back() {
-        if (points.size() == 0) {
-            return;
-        }
-        points.remove(points.size() - 1);
-        Main.map.mapView.repaint();
+    private void doKeyEvent(KeyEvent e) {
+        ///  System.out.println(e);
+        if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
+            if (line.wasSimplified()) {
+                line.clearSimplifiedVersion();
+                repaint();
+                eps=startingEps;
+            }
+            back();
+        }
+        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
+            // first Enter = simplify, second = save the way
+            if (!line.wasSimplified()) {
+                line.simplify(eps);
+                setStatusLine(tr(SIMPLIFYMODE_MESSAGE));
+            } else saveAsWay();
+        }
+        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
+            // more details
+            e.consume();
+            changeEpsilon(epsilonMult);
+        }
+        if (e.getKeyCode() == KeyEvent.VK_UP) {
+            // less details
+            e.consume();
+            changeEpsilon(1/epsilonMult);
+        }
+        if (e.getKeyCode() == KeyEvent.VK_ESCAPE) {
+            // less details
+            e.consume();
+            line.moveToTheEnd();
+        }
+              
+
     }
 
@@ -339,130 +391,19 @@
     }
 
-    private void doKeyEvent(KeyEvent e) {
-        ///  System.out.println(e);
-        if (e.getKeyCode() == KeyEvent.VK_BACK_SPACE) {
-            if (simplePoints!=null) {
-                simplePoints=null;
-                Main.map.mapView.repaint();
-                eps=startingEps;
-            }
-            back();
-        }
-        if (e.getKeyCode() == KeyEvent.VK_ENTER) {
-            // first Enter = simplify, second = save the way
-            if (simplePoints==null) {
-                simplify(eps);
-                setStatusLine(tr(SIMPLIFYMODE_MESSAGE));
-            } else saveAsWay();
-        }
-        if (e.getKeyCode() == KeyEvent.VK_DOWN) {
-            // more details
-            e.consume();
-            changeEpsilon(epsilonMult);
-        }
-        if (e.getKeyCode() == KeyEvent.VK_UP) {
-            // less details
-            e.consume();
-            changeEpsilon(1/epsilonMult);
-        }
-    }
-
-    
-    void changeEpsilon(double k) {
-        //System.out.println(tr("Eps={0}", eps));
-        eps*=k;
-        setStatusLine(tr("Eps={0}", eps));
-        simplify(eps);
-        Main.map.mapView.repaint();
-    }
-    
-    /**
-     * Simplified drawn line, not touching the nodes includes in "fixed" set.
-     */
-    private void simplify(double epsilon) {
-        //System.out.println("Simplify polyline...");
-        int n = points.size();
-        if (n < 3) return;
-        used = new HashSet<LatLon>(n);
-        int start = 0;
-        for (int i = 0; i < n; i++) {
-            LatLon p = points.get(i);
-            if (fixed.contains(p) || i == n - 1) {
-                if (start < 0) {
-                    start = i;
-                } else {
-                    douglasPeucker(start, i, epsilon, 0);
-                }
-            }
-        }
-        simplePoints = new ArrayList<LatLon>(n);
-        simplePoints.addAll(points);
-        simplePoints.retainAll(used);
-        Main.map.mapView.repaint();
-        used = null;
-    }
-
-    /**
-     * Simplification of the line specified by "points" field.
-     * Remainin points are included to "used" set.
-     * @param start - starting index
-     * @param end - ending index
-     * @param epsilon - min point-to line distance in pixels (tolerance)
-     * @param depth - recursion level
-     */
-    private void douglasPeucker(int start, int end, double epsilon, int depth) {
-        if (depth > 500) return;
-        if (end - start < 1) return; // incorrect invocation
-        LatLon first = points.get(start);
-        LatLon last = points.get(end);
-        Point firstp = getPoint(first);
-        Point lastp = getPoint(last);
-        used.add(first);
-        used.add(last);
-
-        if (end - start < 2) return;
-        
-        int farthest_node = -1;
-        double farthest_dist = 0;
-
-        ArrayList<double[]> new_nodes = new ArrayList<double[]>();
-
-        double d = 0;
-
-        for (int i = start + 1; i < end; i++) {
-            d = pointLineDistance(getPoint(points.get(i)), firstp, lastp);
-            if (d > farthest_dist) {
-                farthest_dist = d;
-                farthest_node = i;
-            }
-        }
-
-        if (farthest_dist > epsilon) {
-            douglasPeucker(start, farthest_node, epsilon, depth + 1);
-            douglasPeucker(farthest_node, end, epsilon, depth + 1);
-        }
-    }
-
-    /** Modfified funclion from LakeWalker
-     * Gets distance from point p1 to line p2-p3
-     */
-    public double pointLineDistance(Point p1, Point p2, Point p3) {
-        double x0 = p1.x;        double y0 = p1.y;
-        double x1 = p2.x;        double y1 = p2.y;
-        double x2 = p3.x;        double y2 = p3.y;
-        if (x2 == x1 && y2 == y1) {
-            return Math.hypot(x1 - x0, y1 - y0);
-        } else {
-            return Math.abs((x2-x1)*(y1-y0)-(x1-x0)*(y2-y1))/Math.hypot(x2 - x1,y2 - y1);
-        }
-    }
-
+    @Override
+    protected void updateStatusLine() {
+        Main.map.statusLine.setHelpText(statusText);
+        Main.map.statusLine.repaint();
+    }
+// </editor-fold>
+
+// <editor-fold defaultstate="collapsed" desc="Different action helper methods">
+    public void newDrawing() {
+        eps=startingEps;
+        ready=false;
+        line.clear();
+    }
     private void saveAsWay() {
-        List<LatLon> pts=points;
-        if (simplePoints!=null && simplePoints.size()>0) {
-            // we are drawig simplified version, that exists
-            pts=simplePoints;
-        }
-            
+        List<LatLon> pts=line.getPoints();
         int n = pts.size();
         if (n == 0) return;
@@ -476,7 +417,7 @@
         for (LatLon p : pts) {
             Node nd=null;
-            if (fixed.contains(p)) {
+            if (line.isFixed(p)) {
                 // there may be a node with same ccoords!
-                nd = Main.map.mapView.getNearestNode(getPoint(p), OsmPrimitive.isUsablePredicate);
+                nd = Main.map.mapView.getNearestNode(line.getPoint(p), OsmPrimitive.isUsablePredicate);
             }
             if (nd==null) {
@@ -505,18 +446,21 @@
     }
 
-    private int findClosestPoint(double x, double y, double d) {
-        int n=points.size();
-        int idx=-1;
-        double dist,minD=1e10;
-        for (int i=0;i<n;i++) {
-            dist = Math.sqrt(getPoint(points.get(i)).distanceSq(x,y));
-            if (dist<d && dist<minD) {
-                idx=i;
-                minD=dist;
-            };
-        }
-        return idx;
-    }
-
+    private void repaint() {
+        Main.map.mapView.repaint();
+    }
+
+    public void back() {
+        line.undo();
+        repaint();
+    }
+
+    void changeEpsilon(double k) {
+        //System.out.println(tr("Eps={0}", eps));
+        eps*=k;
+        setStatusLine(tr("Eps={0}", eps));
+        line.simplify(eps);
+        repaint();
+    }
+    
     private void setStatusLine(String tr) {
         statusText=tr;
@@ -548,4 +492,5 @@
         minPixelsBetweenPoints = Main.pref.getDouble("fastdraw.mindelta", 20);
         startingEps = Main.pref.getDouble("fastdraw.startingEps", 20);
+        eps=startingEps;
     }
     
@@ -570,10 +515,18 @@
         
     }
-
+// </editor-fold>
+
+// <editor-fold defaultstate="collapsed" desc="Helper functions">
+    
     private Node getNearestNode(Point point, double maxDist) {
        Node nd = Main.map.mapView.getNearestNode(point, OsmPrimitive.isUsablePredicate);
-       if (nd!=null && getPoint(nd.getCoor()).distance(point)<=maxDist) return nd; 
+       if (nd!=null && line.getPoint(nd.getCoor()).distance(point)<=maxDist) return nd; 
        else return null;
     }
 
+    LatLon getLatLon(MouseEvent e) {
+        return mv.getLatLon(e.getX(), e.getY());
+    }
+// </editor-fold>
+    
 }
