Index: src/org/openstreetmap/josm/actions/AddIntersectionsAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/AddIntersectionsAction.java	(revision 0)
+++ src/org/openstreetmap/josm/actions/AddIntersectionsAction.java	(revision 0)
@@ -0,0 +1,274 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.actions;
+
+import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
+import static org.openstreetmap.josm.tools.I18n.tr;
+
+import java.awt.event.ActionEvent;
+import java.awt.event.KeyEvent;
+import java.awt.geom.Line2D;
+import java.util.ArrayList;
+import java.util.Collection;
+import java.util.Comparator;
+import java.util.LinkedHashSet;
+import java.util.LinkedList;
+import java.util.List;
+import java.util.Set;
+
+import javax.swing.JOptionPane;
+
+import org.openstreetmap.josm.Main;
+import org.openstreetmap.josm.command.AddCommand;
+import org.openstreetmap.josm.command.ChangeCommand;
+import org.openstreetmap.josm.command.Command;
+import org.openstreetmap.josm.command.SequenceCommand;
+import org.openstreetmap.josm.data.coor.EastNorth;
+import org.openstreetmap.josm.data.coor.LatLon;
+import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.NodePositionComparator;
+import org.openstreetmap.josm.data.osm.OsmPrimitive;
+import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.tools.Shortcut;
+
+public class AddIntersectionsAction extends JosmAction {
+    public AddIntersectionsAction() {
+        super(tr("Add nodes at intersections"), "addintersect", tr("Add missing nodes at intersections of selected ways."),
+                Shortcut.registerShortcut("tools:addintersect", tr("Tool: {0}", tr("Add nodes at intersections")), KeyEvent.VK_I, Shortcut.GROUP_EDIT), true);
+        putValue("help", ht("/Action/AddIntersections"));
+    }
+    /**
+     * Will find all intersection and add nodes there for list of given ways. Handles self-intersections too.
+     * And make commands to add the intersection points to ways.
+     * @param List<Way> - a list of ways to test
+     * @return ArrayList<Node> List of new nodes
+     * Prerequisite: no two nodes have the same coordinates.
+     */
+    public static ArrayList<Node> addIntersections(List<Way> ways, boolean test, List<Command> cmds) {
+        //TODO: this is a bit slow - O( (number of nodes)^2 + numberOfIntersections * numberOfNodes )
+
+        //stupid java, cannot instantiate array of generic classes..
+        @SuppressWarnings("unchecked")
+        ArrayList<Node>[] newNodes = new ArrayList[ways.size()];
+        boolean[] changedWays = new boolean[ways.size()];
+
+        Set<Node> intersectionNodes = new LinkedHashSet<Node>();
+
+        for (int pos = 0; pos < ways.size(); pos ++) {
+            newNodes[pos] = new ArrayList<Node>(ways.get(pos).getNodes());
+            changedWays[pos] = false;
+        }
+
+        //iterate over all segment pairs and introduce the intersections
+
+        Comparator<Node> coordsComparator = new NodePositionComparator();
+
+        int seg1Way = 0;
+        int seg1Pos = -1;
+
+        while (true) {
+            //advance to next segment
+            seg1Pos++;
+            if (seg1Pos > newNodes[seg1Way].size() - 2) {
+                seg1Way++;
+                seg1Pos = 0;
+
+                if (seg1Way == ways.size()) { //finished
+                    break;
+                }
+            }
+
+
+            //iterate over secondary segment
+
+            int seg2Way = seg1Way;
+            int seg2Pos = seg1Pos + 1;//skip the adjacent segment
+
+            while (true) {
+
+                //advance to next segment
+                seg2Pos++;
+                if (seg2Pos > newNodes[seg2Way].size() - 2) {
+                    seg2Way++;
+                    seg2Pos = 0;
+
+                    if (seg2Way == ways.size()) { //finished
+                        break;
+                    }
+                }
+
+                //need to get them again every time, because other segments may be changed
+                Node seg1Node1 = newNodes[seg1Way].get(seg1Pos);
+                Node seg1Node2 = newNodes[seg1Way].get(seg1Pos + 1);
+                Node seg2Node1 = newNodes[seg2Way].get(seg2Pos);
+                Node seg2Node2 = newNodes[seg2Way].get(seg2Pos + 1);
+
+                int commonCount = 0;
+                //test if we have common nodes to add.
+                if (seg1Node1 == seg2Node1 || seg1Node1 == seg2Node2) {
+                    commonCount ++;
+
+                    if (seg1Way == seg2Way &&
+                            seg1Pos == 0 &&
+                            seg2Pos == newNodes[seg2Way].size() -2) {
+                        //do not add - this is first and last segment of the same way.
+                    } else {
+                        intersectionNodes.add(seg1Node1);
+                    }
+                }
+
+                if (seg1Node2 == seg2Node1 || seg1Node2 == seg2Node2) {
+                    commonCount ++;
+
+                    intersectionNodes.add(seg1Node2);
+                }
+
+                //no common nodes - find intersection
+                if (commonCount == 0) {
+                    LatLon intersection = getLineLineIntersection(
+                            seg1Node1.getEastNorth().east(), seg1Node1.getEastNorth().north(),
+                            seg1Node2.getEastNorth().east(), seg1Node2.getEastNorth().north(),
+                            seg2Node1.getEastNorth().east(), seg2Node1.getEastNorth().north(),
+                            seg2Node2.getEastNorth().east(), seg2Node2.getEastNorth().north());
+
+                    if (intersection != null) {
+                        if (test) {
+                            intersectionNodes.add(seg2Node1);
+                            return new ArrayList<Node>(intersectionNodes);
+                        }
+
+                        Node newNode = new Node(intersection);
+                        Node intNode = newNode;
+                        boolean insertInSeg1 = false;
+                        boolean insertInSeg2 = false;
+
+                        //find if the intersection point is at end point of one of the segments, if so use that point
+
+                        //segment 1
+                        if (coordsComparator.compare(newNode, seg1Node1) == 0) {
+                            intNode = seg1Node1;
+                        } else if (coordsComparator.compare(newNode, seg1Node2) == 0) {
+                            intNode = seg1Node2;
+                        } else {
+                            insertInSeg1 = true;
+                        }
+
+                        //segment 2
+                        if (coordsComparator.compare(newNode, seg2Node1) == 0) {
+                            intNode = seg2Node1;
+                        } else if (coordsComparator.compare(newNode, seg2Node2) == 0) {
+                            intNode = seg2Node2;
+                        } else {
+                            insertInSeg2 = true;
+                        }
+
+                        if (insertInSeg1) {
+                            newNodes[seg1Way].add(seg1Pos +1, intNode);
+                            changedWays[seg1Way] = true;
+
+                            //fix seg2 position, as indexes have changed, seg2Pos is always bigger than seg1Pos on the same segment.
+                            if (seg2Way == seg1Way) {
+                                seg2Pos ++;
+                            }
+                        }
+
+                        if (insertInSeg2) {
+                            newNodes[seg2Way].add(seg2Pos +1, intNode);
+                            changedWays[seg2Way] = true;
+
+                            //Do not need to compare again to already split segment
+                            seg2Pos ++;
+                        }
+
+                        intersectionNodes.add(intNode);
+
+                        if (intNode == newNode) {
+                            cmds.add(new AddCommand(intNode));
+                        }
+                    }
+                }
+                else if (test && intersectionNodes.size() > 0)
+                    return new ArrayList<Node>(intersectionNodes);
+            }
+        }
+
+        for (int pos = 0; pos < ways.size(); pos ++) {
+            if (changedWays[pos] == false) {
+                continue;
+            }
+
+            Way way = ways.get(pos);
+            Way newWay = new Way(way);
+            newWay.setNodes(newNodes[pos]);
+
+            cmds.add(new ChangeCommand(way, newWay));
+        }
+
+        return new ArrayList<Node>(intersectionNodes);
+    }
+
+
+    /**
+     * Finds the intersection of two lines
+     * @return LatLon null if no intersection was found, the LatLon coordinates of the intersection otherwise
+     */
+    static private LatLon getLineLineIntersection(
+            double x1, double y1, double x2, double y2,
+            double x3, double y3, double x4, double y4) {
+
+        if (!Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return null;
+
+        // Convert line from (point, point) form to ax+by=c
+        double a1 = y2 - y1;
+        double b1 = x1 - x2;
+        double c1 = x2*y1 - x1*y2;
+
+        double a2 = y4 - y3;
+        double b2 = x3 - x4;
+        double c2 = x4*y3 - x3*y4;
+
+        // Solve the equations
+        double det = a1*b2 - a2*b1;
+        if (det == 0) return null; // Lines are parallel
+
+        return Main.proj.eastNorth2latlon(new EastNorth(
+                (b1*c2 - b2*c1)/det,
+                (a2*c1 -a1*c2)/det
+        ));
+    }
+
+    @Override
+    public void actionPerformed(ActionEvent arg0) {
+        if (!isEnabled())
+            return;
+        List<Way> ways = OsmPrimitive.getFilteredList(getCurrentDataSet().getSelected(), Way.class);
+        if (ways.isEmpty()) {
+            JOptionPane.showMessageDialog(
+                    Main.parent,
+                    tr("Please select one or more ways with intersections of segments."),
+                    tr("Information"),
+                    JOptionPane.INFORMATION_MESSAGE
+            );
+            return;
+        }
+
+        LinkedList<Command> cmds = new LinkedList<Command>();
+        addIntersections(ways, false, cmds);
+        if (!cmds.isEmpty()) {
+            Main.main.undoRedo.add(new SequenceCommand(tr("Add nodes at intersections"),cmds));
+        }
+    }
+
+    @Override
+    protected void updateEnabledState() {
+        if (getCurrentDataSet() == null) {
+            setEnabled(false);
+        } else {
+            updateEnabledState(getCurrentDataSet().getSelected());
+        }
+    }
+
+    @Override
+    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
+        setEnabled(selection != null && !selection.isEmpty());
+    }
+}
Index: src/org/openstreetmap/josm/actions/JoinAreasAction.java
===================================================================
--- src/org/openstreetmap/josm/actions/JoinAreasAction.java	(revision 3627)
+++ src/org/openstreetmap/josm/actions/JoinAreasAction.java	(working copy)
@@ -1,6 +1,7 @@
 // License: GPL. Copyright 2007 by Immanuel Scholz and others
 package org.openstreetmap.josm.actions;
 
+import static org.openstreetmap.josm.actions.AddIntersectionsAction.addIntersections;
 import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.combineTigerTags;
 import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.completeTagCollectionForEditing;
 import static org.openstreetmap.josm.gui.conflict.tags.TagConflictResolutionUtil.normalizeTagCollectionBeforeEditing;
@@ -11,11 +12,9 @@
 import java.awt.event.ActionEvent;
 import java.awt.event.KeyEvent;
 import java.awt.geom.Area;
-import java.awt.geom.Line2D;
 import java.util.ArrayList;
 import java.util.Collection;
 import java.util.Collections;
-import java.util.Comparator;
 import java.util.HashMap;
 import java.util.HashSet;
 import java.util.LinkedHashSet;
@@ -38,9 +37,9 @@
 import org.openstreetmap.josm.corrector.UserCancelException;
 import org.openstreetmap.josm.data.UndoRedoHandler;
 import org.openstreetmap.josm.data.coor.EastNorth;
-import org.openstreetmap.josm.data.coor.LatLon;
 import org.openstreetmap.josm.data.osm.DataSet;
 import org.openstreetmap.josm.data.osm.Node;
+import org.openstreetmap.josm.data.osm.NodePositionComparator;
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Relation;
 import org.openstreetmap.josm.data.osm.RelationMember;
@@ -289,31 +288,7 @@
         }
     }
 
-    /**
-     * Provides some node order , based on coordinates, nodes with equal coordinates are equal.
-     * @author viesturs
-     *
-     */
-    private class NodePositionComparator implements Comparator<Node> {
 
-        @Override
-        public int compare(Node n1, Node n2) {
-
-            double dLat = n1.getCoor().lat() - n2.getCoor().lat();
-            double dLon = n1.getCoor().lon() - n2.getCoor().lon();
-
-            if (dLat > 0)
-                return 1;
-            else if (dLat < 0)
-                return -1;
-            else if (dLon == 0) //dlat is 0 here
-                return 0;
-            else
-                return dLon > 0 ? 1 : -1;
-        }
-    }
-
-
     /**
      * Helper storage class for finding findOuterWays
      * @author viesturs
@@ -429,7 +404,7 @@
         }
 
         //find intersection points
-        ArrayList<Node> nodes = addIntersections(allStartingWays, true);
+        ArrayList<Node> nodes = addIntersections(allStartingWays, true, cmds);
         return nodes.size() > 0;
     }
 
@@ -465,7 +440,7 @@
         }
 
         //find intersection points
-        ArrayList<Node> nodes = addIntersections(allStartingWays, false);
+        ArrayList<Node> nodes = addIntersections(allStartingWays, false, cmds);
 
         //no intersections, return.
         if (nodes.size() == 0) return result;
@@ -660,209 +635,7 @@
     }
 
 
-
     /**
-     * Will find all intersection and add nodes there for list of given ways. Handles self-intersections too.
-     * And make commands to add the intersection points to ways.
-     * @param List<Way> - a list of ways to test
-     * @return ArrayList<Node> List of new nodes
-     * Prerequisite: no two nodes have the same coordinates.
-     */
-    private ArrayList<Node> addIntersections(List<Way> ways, boolean test) {
-        //TODO: this is a bit slow - O( (number of nodes)^2 + numberOfIntersections * numberOfNodes )
-
-        //stupid java, cannot instantiate array of generic classes..
-        @SuppressWarnings("unchecked")
-        ArrayList<Node>[] newNodes = new ArrayList[ways.size()];
-        boolean[] changedWays = new boolean[ways.size()];
-
-        Set<Node> intersectionNodes = new LinkedHashSet<Node>();
-
-        for (int pos = 0; pos < ways.size(); pos ++) {
-            newNodes[pos] = new ArrayList<Node>(ways.get(pos).getNodes());
-            changedWays[pos] = false;
-        }
-
-        //iterate over all segment pairs and introduce the intersections
-
-        Comparator<Node> coordsComparator = new NodePositionComparator();
-
-        int seg1Way = 0;
-        int seg1Pos = -1;
-
-        while (true) {
-            //advance to next segment
-            seg1Pos++;
-            if (seg1Pos > newNodes[seg1Way].size() - 2) {
-                seg1Way++;
-                seg1Pos = 0;
-
-                if (seg1Way == ways.size()) { //finished
-                    break;
-                }
-            }
-
-
-            //iterate over secondary segment
-
-            int seg2Way = seg1Way;
-            int seg2Pos = seg1Pos + 1;//skip the adjacent segment
-
-            while (true) {
-
-                //advance to next segment
-                seg2Pos++;
-                if (seg2Pos > newNodes[seg2Way].size() - 2) {
-                    seg2Way++;
-                    seg2Pos = 0;
-
-                    if (seg2Way == ways.size()) { //finished
-                        break;
-                    }
-                }
-
-                //need to get them again every time, because other segments may be changed
-                Node seg1Node1 = newNodes[seg1Way].get(seg1Pos);
-                Node seg1Node2 = newNodes[seg1Way].get(seg1Pos + 1);
-                Node seg2Node1 = newNodes[seg2Way].get(seg2Pos);
-                Node seg2Node2 = newNodes[seg2Way].get(seg2Pos + 1);
-
-                int commonCount = 0;
-                //test if we have common nodes to add.
-                if (seg1Node1 == seg2Node1 || seg1Node1 == seg2Node2) {
-                    commonCount ++;
-
-                    if (seg1Way == seg2Way &&
-                            seg1Pos == 0 &&
-                            seg2Pos == newNodes[seg2Way].size() -2) {
-                        //do not add - this is first and last segment of the same way.
-                    } else {
-                        intersectionNodes.add(seg1Node1);
-                    }
-                }
-
-                if (seg1Node2 == seg2Node1 || seg1Node2 == seg2Node2) {
-                    commonCount ++;
-
-                    intersectionNodes.add(seg1Node2);
-                }
-
-                //no common nodes - find intersection
-                if (commonCount == 0) {
-                    LatLon intersection = getLineLineIntersection(
-                            seg1Node1.getEastNorth().east(), seg1Node1.getEastNorth().north(),
-                            seg1Node2.getEastNorth().east(), seg1Node2.getEastNorth().north(),
-                            seg2Node1.getEastNorth().east(), seg2Node1.getEastNorth().north(),
-                            seg2Node2.getEastNorth().east(), seg2Node2.getEastNorth().north());
-
-                    if (intersection != null) {
-                        if (test) {
-                            intersectionNodes.add(seg2Node1);
-                            return new ArrayList<Node>(intersectionNodes);
-                        }
-
-                        Node newNode = new Node(intersection);
-                        Node intNode = newNode;
-                        boolean insertInSeg1 = false;
-                        boolean insertInSeg2 = false;
-
-                        //find if the intersection point is at end point of one of the segments, if so use that point
-
-                        //segment 1
-                        if (coordsComparator.compare(newNode, seg1Node1) == 0) {
-                            intNode = seg1Node1;
-                        } else if (coordsComparator.compare(newNode, seg1Node2) == 0) {
-                            intNode = seg1Node2;
-                        } else {
-                            insertInSeg1 = true;
-                        }
-
-                        //segment 2
-                        if (coordsComparator.compare(newNode, seg2Node1) == 0) {
-                            intNode = seg2Node1;
-                        } else if (coordsComparator.compare(newNode, seg2Node2) == 0) {
-                            intNode = seg2Node2;
-                        } else {
-                            insertInSeg2 = true;
-                        }
-
-                        if (insertInSeg1) {
-                            newNodes[seg1Way].add(seg1Pos +1, intNode);
-                            changedWays[seg1Way] = true;
-
-                            //fix seg2 position, as indexes have changed, seg2Pos is always bigger than seg1Pos on the same segment.
-                            if (seg2Way == seg1Way) {
-                                seg2Pos ++;
-                            }
-                        }
-
-                        if (insertInSeg2) {
-                            newNodes[seg2Way].add(seg2Pos +1, intNode);
-                            changedWays[seg2Way] = true;
-
-                            //Do not need to compare again to already split segment
-                            seg2Pos ++;
-                        }
-
-                        intersectionNodes.add(intNode);
-
-                        if (intNode == newNode) {
-                            cmds.add(new AddCommand(intNode));
-                        }
-                    }
-                }
-                else if (test && intersectionNodes.size() > 0)
-                    return new ArrayList<Node>(intersectionNodes);
-            }
-        }
-
-        for (int pos = 0; pos < ways.size(); pos ++) {
-            if (changedWays[pos] == false) {
-                continue;
-            }
-
-            Way way = ways.get(pos);
-            Way newWay = new Way(way);
-            newWay.setNodes(newNodes[pos]);
-
-            cmds.add(new ChangeCommand(way, newWay));
-        }
-
-        return new ArrayList<Node>(intersectionNodes);
-    }
-
-    /**
-     * Finds the intersection of two lines
-     * @return LatLon null if no intersection was found, the LatLon coordinates of the intersection otherwise
-     */
-    static private LatLon getLineLineIntersection(
-            double x1, double y1, double x2, double y2,
-            double x3, double y3, double x4, double y4) {
-
-        if (!Line2D.linesIntersect(x1, y1, x2, y2, x3, y3, x4, y4)) return null;
-
-        // Convert line from (point, point) form to ax+by=c
-        double a1 = y2 - y1;
-        double b1 = x1 - x2;
-        double c1 = x2*y1 - x1*y2;
-
-        double a2 = y4 - y3;
-        double b2 = x3 - x4;
-        double c2 = x4*y3 - x3*y4;
-
-        // Solve the equations
-        double det = a1*b2 - a2*b1;
-        if (det == 0) return null; // Lines are parallel
-
-        return Main.proj.eastNorth2latlon(new EastNorth(
-                (b1*c2 - b2*c1)/det,
-                (a2*c1 -a1*c2)/det
-        ));
-    }
-
-
-
-    /**
      * Commits the command list with a description
      * @param String The description of what the commands do
      */
Index: src/org/openstreetmap/josm/gui/MainMenu.java
===================================================================
--- src/org/openstreetmap/josm/gui/MainMenu.java	(revision 3627)
+++ src/org/openstreetmap/josm/gui/MainMenu.java	(working copy)
@@ -16,6 +16,7 @@
 
 import org.openstreetmap.josm.Main;
 import org.openstreetmap.josm.actions.AboutAction;
+import org.openstreetmap.josm.actions.AddIntersectionsAction;
 import org.openstreetmap.josm.actions.AddNodeAction;
 import org.openstreetmap.josm.actions.AlignInCircleAction;
 import org.openstreetmap.josm.actions.AlignInLineAction;
@@ -51,6 +52,7 @@
 import org.openstreetmap.josm.actions.OpenFileAction;
 import org.openstreetmap.josm.actions.OpenLocationAction;
 import org.openstreetmap.josm.actions.OrthogonalizeAction;
+import org.openstreetmap.josm.actions.OrthogonalizeAction.Undo;
 import org.openstreetmap.josm.actions.PasteAction;
 import org.openstreetmap.josm.actions.PasteTagsAction;
 import org.openstreetmap.josm.actions.PreferencesAction;
@@ -75,7 +77,6 @@
 import org.openstreetmap.josm.actions.WireframeToggleAction;
 import org.openstreetmap.josm.actions.ZoomInAction;
 import org.openstreetmap.josm.actions.ZoomOutAction;
-import org.openstreetmap.josm.actions.OrthogonalizeAction.Undo;
 import org.openstreetmap.josm.actions.audio.AudioBackAction;
 import org.openstreetmap.josm.actions.audio.AudioFasterAction;
 import org.openstreetmap.josm.actions.audio.AudioFwdAction;
@@ -152,6 +153,7 @@
     public final JosmAction joinNodeWay = new JoinNodeWayAction();
     public final JosmAction unglueNodes = new UnGlueAction();
     public final JosmAction simplifyWay = new SimplifyWayAction();
+    public final JosmAction addIntersections = new AddIntersectionsAction();
     public final JosmAction joinAreas = new JoinAreasAction();
     public final InfoAction info = new InfoAction();
     public final HistoryInfoAction historyinfo = new HistoryInfoAction();
@@ -315,6 +317,7 @@
         add(toolsMenu, mergeNodes);
         add(toolsMenu, joinNodeWay);
         add(toolsMenu, unglueNodes);
+        add(toolsMenu, addIntersections);
         add(toolsMenu, joinAreas);
         toolsMenu.addSeparator();
         add(toolsMenu, info);
Index: src/org/openstreetmap/josm/data/osm/NodePositionComparator.java
===================================================================
--- src/org/openstreetmap/josm/data/osm/NodePositionComparator.java	(revision 0)
+++ src/org/openstreetmap/josm/data/osm/NodePositionComparator.java	(revision 0)
@@ -0,0 +1,28 @@
+// License: GPL. For details, see LICENSE file.
+package org.openstreetmap.josm.data.osm;
+
+import java.util.Comparator;
+
+/**
+ * Provides some node order , based on coordinates, nodes with equal coordinates are equal.
+ * @author viesturs
+ *
+ */
+public class NodePositionComparator implements Comparator<Node> {
+
+    @Override
+    public int compare(Node n1, Node n2) {
+
+        double dLat = n1.getCoor().lat() - n2.getCoor().lat();
+        double dLon = n1.getCoor().lon() - n2.getCoor().lon();
+
+        if (dLat > 0)
+            return 1;
+        else if (dLat < 0)
+            return -1;
+        else if (dLon == 0) //dlat is 0 here
+            return 0;
+        else
+            return dLon > 0 ? 1 : -1;
+    }
+}
