Index: src/org/openstreetmap/josm/actions/CreateCircleAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/CreateCircleAction.java	(revision 1738)
+++ src/org/openstreetmap/josm/actions/CreateCircleAction.java	(working copy)
@@ -13,6 +13,7 @@
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.command.Command;
 import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.DeleteCommand;
 import org.openstreetmap.josm.command.ChangeCommand;
 import org.openstreetmap.josm.command.SequenceCommand;
 import org.openstreetmap.josm.data.coor.EastNorth;
@@ -21,35 +22,37 @@
 import org.openstreetmap.josm.data.osm.Way;
 import org.openstreetmap.josm.tools.Shortcut;
 
+import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
+
 /**
- * Create a new circle from three selected nodes--or a way with 3 nodes. (Useful for roundabouts)
+ * - Create a new circle from two selected nodes or a way with 2 nodes which represent the diameter of the circle.
+ * - Create a new circle from three selected nodes--or a way with 3 nodes.
+ * - Useful for roundabouts
  *
  * Note: If a way is selected, it is changed. If nodes are selected a new way is created.
- *       So if you've got a way with 3 nodes it makes a difference between running this on the way or the nodes!
+ *       So if you've got a way with nodes it makes a difference between running this on the way or the nodes!
  *
  * BTW: Someone might want to implement projection corrections for this...
  *
  * @author Henry Loenwind, based on much copy&Paste from other Actions.
+ * @author Sebastian Masch
  */
 public final class CreateCircleAction extends JosmAction {
 
     public CreateCircleAction() {
         super(tr("Create Circle"), "createcircle", tr("Create a circle from three selected nodes."),
-        Shortcut.registerShortcut("tools:createcircle", tr("Tool: {0}", tr("Create Circle")), KeyEvent.VK_O, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
+                Shortcut.registerShortcut("tools:createcircle", tr("Tool: {0}", tr("Create Circle")), KeyEvent.VK_O, Shortcut.GROUP_EDIT, Shortcut.SHIFT_DEFAULT), true);
     }
 
     private double calcang(double xc, double yc, double x, double y) {
         // calculate the angle from xc|yc to x|y
-        if (xc == x && yc == y) {
+        if (xc == x && yc == y)
             return 0; // actually invalid, but we won't have this case in this context
-        }
         double yd = Math.abs(y - yc);
-        if (yd == 0 && xc < x) {
+        if (yd == 0 && xc < x)
             return 0;
-        }
-        if (yd == 0 && xc > x) {
+        if (yd == 0 && xc > x)
             return Math.PI;
-        }
         double xd = Math.abs(x - xc);
         double a = Math.atan2(xd, yd);
         if (y > yc) {
@@ -81,102 +84,181 @@
         Way existingWay = null;
 
         for (OsmPrimitive osm : sel)
-            if (osm instanceof Node)
+            if (osm instanceof Node) {
                 nodes.add((Node)osm);
+            }
 
         // special case if no single nodes are selected and exactly one way is:
         // then use the way's nodes
-        if ((nodes.size() == 0) && (sel.size() == 1))
+        if ((nodes.size() == 0) && (sel.size() == 1)) {
             for (OsmPrimitive osm : sel)
                 if (osm instanceof Way) {
                     existingWay = ((Way)osm);
                     for (Node n : ((Way)osm).nodes)
                     {
-                        if(!nodes.contains(n))
+                        if(!nodes.contains(n)) {
                             nodes.add(n);
+                        }
                     }
                 }
-
-        if (nodes.size() != 3) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Please select exactly three nodes or one way with exactly three nodes."));
-            return;
         }
 
-        // let's get some shorter names
-        Node   n1 = ((Node)nodes.toArray()[0]);
-        double x1 = n1.getEastNorth().east();
-        double y1 = n1.getEastNorth().north();
-        Node   n2 = ((Node)nodes.toArray()[1]);
-        double x2 = n2.getEastNorth().east();
-        double y2 = n2.getEastNorth().north();
-        Node   n3 = ((Node)nodes.toArray()[2]);
-        double x3 = n3.getEastNorth().east();
-        double y3 = n3.getEastNorth().north();
+        // now we can start doing things to OSM data
+        Collection<Command> cmds = new LinkedList<Command>();
 
-        // calculate the center (xc/yc)
-        double s = 0.5*((x2 - x3)*(x1 - x3) - (y2 - y3)*(y3 - y1));
-        double sUnder = (x1 - x2)*(y3 - y1) - (y2 - y1)*(x1 - x3);
+        if (nodes.size() == 2) {
+            // diameter: two single nodes needed or a way with two nodes
 
-        if (sUnder == 0) {
-            JOptionPane.showMessageDialog(Main.parent, tr("Those nodes are not in a circle."));
-            return;
-        }
+            Node   n1 = ((Node)nodes.toArray()[0]);
+            double x1 = n1.getEastNorth().east();
+            double y1 = n1.getEastNorth().north();
+            Node   n2 = ((Node)nodes.toArray()[1]);
+            double x2 = n2.getEastNorth().east();
+            double y2 = n2.getEastNorth().north();
 
-        s /= sUnder;
+            // calculate the center (xc/yc)
+            double xc = 0.5 * (x1 + x2);
+            double yc = 0.5 * (y1 + y2);
 
-        double xc = 0.5*(x1 + x2) + s*(y2 - y1);
-        double yc = 0.5*(y1 + y2) + s*(x1 - x2);
+            // calculate the radius (r)
+            double r = Math.sqrt(Math.pow(xc-x1,2) + Math.pow(yc-y1,2));
 
-        // calculate the radius (r)
-        double r = Math.sqrt(Math.pow(xc-x1,2) + Math.pow(yc-y1,2));
+            // find where to put the existing nodes
+            double a1 = calcang(xc, yc, x1, y1);
+            double a2 = calcang(xc, yc, x2, y2);
+            if (a1 < a2) { double at = a1; Node nt = n1; a1 = a2; n1 = n2; a2 = at; n2 = nt; }
 
-        // find where to put the existing nodes
-        double a1 = calcang(xc, yc, x1, y1);
-        double a2 = calcang(xc, yc, x2, y2);
-        double a3 = calcang(xc, yc, x3, y3);
-        if (a1 < a2) { double at = a1; Node nt = n1; a1 = a2; n1 = n2; a2 = at; n2 = nt; }
-        if (a2 < a3) { double at = a2; Node nt = n2; a2 = a3; n2 = n3; a3 = at; n3 = nt; }
-        if (a1 < a2) { double at = a1; Node nt = n1; a1 = a2; n1 = n2; a2 = at; n2 = nt; }
+            // build a way for the circle
+            Way wayToAdd;
+            if (existingWay == null) {
+                wayToAdd = new Way();
+            } else {
+                // re-use existing way if it was selected
+                wayToAdd = new Way(existingWay);
+                wayToAdd.nodes.clear();
+            }
 
-        // now we can start doing thigs to OSM data
-        Collection<Command> cmds = new LinkedList<Command>();
+            for (int i = 1; i <= numberOfNodesInCircle; i++) {
+                double a = a2 + 2*Math.PI*(1.0 - i/(double)numberOfNodesInCircle); // "1-" to get it clock-wise
 
-        // build a way for the circle
-        Way wayToAdd;
-        if (existingWay == null) {
-            wayToAdd = new Way();
-        } else {
-            // re-use existing way if it was selected
-            wayToAdd = new Way(existingWay);
-            wayToAdd.nodes.clear();
-        }
-        for (int i = 1; i <= numberOfNodesInCircle; i++) {
-            double a = 2*Math.PI*(1.0 - i/(double)numberOfNodesInCircle); // "1-" to get it clock-wise
-            // insert existing nodes if they fit before this new node (999 means "already added this node")
-            if (a1 < 999 && a1 > a) {
-                wayToAdd.nodes.add(n1);
-                a1 = 999;
+                // insert existing nodes if they fit before this new node (999 means "already added this node")
+                if ((a1 < 999) && (a1 > a - 1E-9) && (a1 < a + 1E-9)) {
+                    wayToAdd.nodes.add(n1);
+                    a1 = 999;
+                }
+                else if ((a2 < 999) && (a2 > a - 1E-9) && (a2 < a + 1E-9)) {
+                    wayToAdd.nodes.add(n2);
+                    a2 = 999;
+                }
+                else {
+                    // get the position of the new node and insert it
+                    double x = xc + r*Math.cos(a);
+                    double y = yc + r*Math.sin(a);
+                    Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
+                    wayToAdd.nodes.add(n);
+                    cmds.add(new AddCommand(n));
+                }
             }
-            if (a2 < 999 && a2 > a) {
-                wayToAdd.nodes.add(n2);
-                a2 = 999;
+            wayToAdd.nodes.add(wayToAdd.nodes.get(0)); // close the circle
+            if (existingWay == null) {
+                cmds.add(new AddCommand(wayToAdd));
+            } else {
+                cmds.add(new ChangeCommand(existingWay, wayToAdd));
             }
-            if (a3 < 999 && a3 > a) {
-                wayToAdd.nodes.add(n3);
-                a3 = 999;
+
+            // the first node may be unused/abandoned if createcircle.nodecount is odd
+            if (a1 < 999) {
+                // if it is, delete it
+                CollectBackReferencesVisitor refs = new CollectBackReferencesVisitor(Main.ds);
+                refs.visit(n1);
+                if (refs.data.isEmpty() || ((refs.data.size() == 1) && (refs.data.contains(existingWay)))) {
+                    cmds.add(new DeleteCommand(n1));
+                }
+
+                // or insert it
+                // wayToAdd.nodes.add((numberOfNodesInCircle - 1) / 2, n1);
             }
-            // get the position of the new node and insert it
-            double x = xc + r*Math.cos(a);
-            double y = yc + r*Math.sin(a);
-            Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
-            wayToAdd.nodes.add(n);
-            cmds.add(new AddCommand(n));
-        }
-        wayToAdd.nodes.add(wayToAdd.nodes.get(0)); // close the circle
-        if (existingWay == null) {
-            cmds.add(new AddCommand(wayToAdd));
+
+        } else if (nodes.size() == 3) {
+            // triangle: three single nodes needed or a way with three nodes
+
+            // let's get some shorter names
+            Node   n1 = ((Node)nodes.toArray()[0]);
+            double x1 = n1.getEastNorth().east();
+            double y1 = n1.getEastNorth().north();
+            Node   n2 = ((Node)nodes.toArray()[1]);
+            double x2 = n2.getEastNorth().east();
+            double y2 = n2.getEastNorth().north();
+            Node   n3 = ((Node)nodes.toArray()[2]);
+            double x3 = n3.getEastNorth().east();
+            double y3 = n3.getEastNorth().north();
+
+            // calculate the center (xc/yc)
+            double s = 0.5*((x2 - x3)*(x1 - x3) - (y2 - y3)*(y3 - y1));
+            double sUnder = (x1 - x2)*(y3 - y1) - (y2 - y1)*(x1 - x3);
+
+            if (sUnder == 0) {
+                JOptionPane.showMessageDialog(Main.parent, tr("Those nodes are not in a circle."));
+                return;
+            }
+
+            s /= sUnder;
+
+            double xc = 0.5*(x1 + x2) + s*(y2 - y1);
+            double yc = 0.5*(y1 + y2) + s*(x1 - x2);
+
+            // calculate the radius (r)
+            double r = Math.sqrt(Math.pow(xc-x1,2) + Math.pow(yc-y1,2));
+
+            // find where to put the existing nodes
+            double a1 = calcang(xc, yc, x1, y1);
+            double a2 = calcang(xc, yc, x2, y2);
+            double a3 = calcang(xc, yc, x3, y3);
+            if (a1 < a2) { double at = a1; Node nt = n1; a1 = a2; n1 = n2; a2 = at; n2 = nt; }
+            if (a2 < a3) { double at = a2; Node nt = n2; a2 = a3; n2 = n3; a3 = at; n3 = nt; }
+            if (a1 < a2) { double at = a1; Node nt = n1; a1 = a2; n1 = n2; a2 = at; n2 = nt; }
+
+            // build a way for the circle
+            Way wayToAdd;
+            if (existingWay == null) {
+                wayToAdd = new Way();
+            } else {
+                // re-use existing way if it was selected
+                wayToAdd = new Way(existingWay);
+                wayToAdd.nodes.clear();
+            }
+            for (int i = 1; i <= numberOfNodesInCircle; i++) {
+                double a = 2*Math.PI*(1.0 - i/(double)numberOfNodesInCircle); // "1-" to get it clock-wise
+                // insert existing nodes if they fit before this new node (999 means "already added this node")
+                if (a1 < 999 && a1 > a) {
+                    wayToAdd.nodes.add(n1);
+                    a1 = 999;
+                }
+                if (a2 < 999 && a2 > a) {
+                    wayToAdd.nodes.add(n2);
+                    a2 = 999;
+                }
+                if (a3 < 999 && a3 > a) {
+                    wayToAdd.nodes.add(n3);
+                    a3 = 999;
+                }
+                // get the position of the new node and insert it
+                double x = xc + r*Math.cos(a);
+                double y = yc + r*Math.sin(a);
+                Node n = new Node(Main.proj.eastNorth2latlon(new EastNorth(x,y)));
+                wayToAdd.nodes.add(n);
+                cmds.add(new AddCommand(n));
+            }
+            wayToAdd.nodes.add(wayToAdd.nodes.get(0)); // close the circle
+            if (existingWay == null) {
+                cmds.add(new AddCommand(wayToAdd));
+            } else {
+                cmds.add(new ChangeCommand(existingWay, wayToAdd));
+            }
+
         } else {
-            cmds.add(new ChangeCommand(existingWay, wayToAdd));
+            JOptionPane.showMessageDialog(Main.parent, tr("Please select exactly two or three nodes or one way with exactly two or three nodes."));
+            return;
         }
 
         Main.main.undoRedo.add(new SequenceCommand(tr("Create Circle"), cmds));
