Index: applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/Building.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/Building.java	(revision 34723)
+++ applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/Building.java	(revision 34724)
@@ -13,7 +13,9 @@
 import java.util.Collection;
 import java.util.Collections;
+import java.util.LinkedHashSet;
 import java.util.LinkedList;
 import java.util.List;
 import java.util.Map.Entry;
+import java.util.Set;
 
 import javax.swing.JOptionPane;
@@ -27,5 +29,4 @@
 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.BBox;
 import org.openstreetmap.josm.data.osm.DataSet;
@@ -50,4 +51,5 @@
     private AngleSnap angleSnap = new AngleSnap();
     private Double drawingAngle;
+    private final static double EQUAL_NODE_DIST_TOLERANCE = 1e-6;
 
     public void clearAngleSnap() {
@@ -103,9 +105,4 @@
     public void setBase(EastNorth base) {
         en[0] = base;
-        updMetrics();
-    }
-
-    public void setBase(Node base) {
-        en[0] = latlon2eastNorth(base.getCoor());
         updMetrics();
     }
@@ -145,5 +142,5 @@
     }
 
-    public void setLengthWidth(double length, double width) {
+    private void setLengthWidth(double length, double width) {
         this.len = length;
         this.width = width;
@@ -231,18 +228,9 @@
 
     private Node findNode(EastNorth pos) {
-        DataSet ds = MainApplication.getLayerManager().getEditDataSet();
-        LatLon l = eastNorth2latlon(pos);
-        List<Node> nodes = ds.searchNodes(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001,
-                l.lon() + 0.0000001, l.lat() + 0.0000001));
-        Node bestnode = null;
-        double mindist = 0.0003;
-        for (Node n : nodes) {
-            double dist = n.getCoor().distanceSq(l);
-            if (dist < mindist && n.isUsable()) {
-                bestnode = n;
-                mindist = dist;
-            }
-        }
-        return bestnode;
+        MapView mv = MainApplication.getMap().mapView;
+        Node n = mv.getNearestNode(mv.getPoint(eastNorth2latlon(pos)), OsmPrimitive::isSelectable);
+        if (n == null)
+            return null;
+        return n.getEastNorth().distance(pos) <= EQUAL_NODE_DIST_TOLERANCE ? n : null;
     }
 
@@ -326,4 +314,5 @@
         }
 
+        snapBuildings(w, nodes, addNodesCmd);
         if (addNodesCmd.size() > 0) {
             Command addNodes = new SequenceCommand(tr("Add nodes for building"), addNodesCmd);
@@ -332,9 +321,5 @@
 
         // Nodes must be selected for create circle action
-        for (int i = 0; i < 2; i++) {
-            if (created[i]) {
-                ds.addSelected(nodes[i]);
-            }
-        }
+        ds.addSelected(w.getNodes());
 
         CreateCircleAction action = new CreateCircleAction();
@@ -342,4 +327,5 @@
         action.actionPerformed(null);
 
+        // restore selection
         ds.clearSelection();
         ds.addSelected(selectedPrimitives);
@@ -403,31 +389,5 @@
 
         if (snap) {
-            // calculate BBox which is slightly larger than the new building
-            BBox searchBox = new BBox();
-            final double maxDist = 0.001;
-            List<Node> wayNodes = w.getNodes();
-            for (Node n : nodes) {
-                LatLon l = eastNorth2latlon(n.getEastNorth());
-                searchBox.add(new BBox(l.lon() - 0.0000001, l.lat() - 0.0000001,
-                        l.lon() + 0.0000001, l.lat() + 0.0000001));
-            }
-            // find the ways which might be snapped to the new building
-            List<Way> others = ds.searchWays(searchBox);
-            // add nodes of existing buildings to the new one
-            others.removeIf(o -> o.get("building") == null || !o.isUsable());
-            for (Way other : others) {
-                snapToWay(wayNodes, other.getNodes(), maxDist);
-                w.setNodes(wayNodes);
-            }
-            // add new nodes to existing buildings
-            for (Way other : others) {
-                List<Node> otherNodes = other.getNodes();
-                snapToWay(otherNodes, Arrays.asList(nodes), maxDist);
-                if (otherNodes.size() != other.getNodesCount()) {
-                    Way newWay = new Way(other);
-                    newWay.setNodes(otherNodes);
-                    cmds.add(new ChangeCommand(other, newWay));
-                }
-            }
+            snapBuildings(w, nodes, cmds);
         }
         Command c = new SequenceCommand(tr("Create building"), cmds);
@@ -436,7 +396,36 @@
     }
 
+    private void snapBuildings(Way w, Node[] nodes, Collection<Command> cmds) {
+        // calculate BBox which is slightly larger than the new building
+        List<Node> wayNodes = w.getNodes();
+        // find the ways which might be snapped to the new building
+        Set<Way> others = new LinkedHashSet<>();
+        MapView mv = MainApplication.getMap().mapView;
+        for (Node n : nodes) {
+            Way w2 = mv.getNearestWay(mv.getPoint(n), OsmPrimitive::isSelectable);
+            if (w2 != null && w2.get("building") != null)
+                others.add(w2);
+        }
+        // add nodes of existing buildings to the new one
+        for (Way other : others) {
+            snapToWay(wayNodes, other.getNodes());
+            w.setNodes(wayNodes);
+        }
+        // add new nodes to existing buildings
+        for (Way other : others) {
+            List<Node> otherNodes = other.getNodes();
+            snapToWay(otherNodes, Arrays.asList(nodes));
+            if (otherNodes.size() != other.getNodesCount()) {
+                Way newWay = new Way(other);
+                newWay.setNodes(otherNodes);
+                cmds.add(new ChangeCommand(other, newWay));
+            }
+        }
+
+    }
+
     /**
-     * Add all nodes in otherNodes to wayNodes that are within maxDist to the
-     * segments described by wayNodes.
+     * Add all nodes in otherNodes to wayNodes that are within snap distance to
+     * the segments described by wayNodes.
      *
      * @param wayNodes
@@ -444,9 +433,6 @@
      * @param otherNodes
      *            other nodes
-     * @param maxDist
-     *            maximum distance as square of the euclidean distance between
-     *            way segment and node
      */
-    private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes, double maxDist) {
+    private static void snapToWay(List<Node> wayNodes, Collection<Node> otherNodes) {
         for (int i = 0; i < wayNodes.size(); i++) {
             Node n0 = wayNodes.get(i);
@@ -455,10 +441,9 @@
                 if (n2 == n0 || n2 == n1)
                     continue;
-                EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(),
-                        n2.getEastNorth());
-                if (x.distanceSq(n2.getEastNorth()) < maxDist) {
+                EastNorth x = Geometry.closestPointToSegment(n0.getEastNorth(), n1.getEastNorth(), n2.getEastNorth());
+                if (x.distance(n2.getEastNorth()) <= EQUAL_NODE_DIST_TOLERANCE && !wayNodes.contains(n2)) {
                     wayNodes.add(i + 1, n2);
-                    i--; // we may add multiple nodes to one segment, so repeat
-                         // it
+                    // we may add multiple nodes to one segment, so repeat it
+                    i--;
                     break;
                 }
Index: applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java
===================================================================
--- applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(revision 34723)
+++ applications/editors/josm/plugins/buildings_tools/src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(revision 34724)
@@ -29,4 +29,5 @@
 import org.openstreetmap.josm.data.osm.OsmPrimitive;
 import org.openstreetmap.josm.data.osm.Way;
+import org.openstreetmap.josm.data.osm.WaySegment;
 import org.openstreetmap.josm.data.osm.event.SelectionEventManager;
 import org.openstreetmap.josm.data.preferences.NamedColorProperty;
@@ -39,4 +40,5 @@
 import org.openstreetmap.josm.gui.util.KeyPressReleaseListener;
 import org.openstreetmap.josm.gui.util.ModifierExListener;
+import org.openstreetmap.josm.tools.Geometry;
 import org.openstreetmap.josm.tools.ImageProvider;
 import org.openstreetmap.josm.tools.Logging;
@@ -51,4 +53,5 @@
     private final Cursor cursorCrosshair;
     private final Cursor cursorJoinNode;
+    private final Cursor cursorJoinWay;
     private Cursor currCursor;
     private Cursor customCursor;
@@ -72,4 +75,5 @@
         cursorCrosshair = getCursor();
         cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
+        cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway");
         currCursor = cursorCrosshair;
     }
@@ -201,15 +205,21 @@
 
     private EastNorth getEastNorth() {
-        Node n;
-        if (ctrl) {
-            n = null;
-        } else {
-            n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
-        }
-        if (n == null) {
-            return latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y));
-        } else {
-            return latlon2eastNorth(n.getCoor());
-        }
+        if (!ctrl) {
+            Node n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
+            if (n != null)
+                return latlon2eastNorth(n.getCoor());
+            WaySegment ws = MainApplication.getMap().mapView.getNearestWaySegment(mousePos,
+                    OsmPrimitive::isSelectable);
+            if (ws != null && ws.way.get("building") != null) {
+                EastNorth p1 = ws.getFirstNode().getEastNorth();
+                EastNorth p2 = ws.getSecondNode().getEastNorth();
+                EastNorth enX = Geometry.closestPointToSegment(p1, p2,
+                        MainApplication.getMap().mapView.getEastNorth(mousePos.x, mousePos.y));
+                if (enX != null) {
+                    return enX;
+                }
+            }
+        }
+        return latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y));
     }
 
@@ -222,6 +232,6 @@
         EastNorth p = getEastNorth();
         if (isRectDrawing()) {
-                building.setPlaceRect(p);
-                return shift ? Mode.DrawingAngFix : Mode.None;
+            building.setPlaceRect(p);
+            return shift ? Mode.DrawingAngFix : Mode.None;
         } else if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
             if (ToolSettings.getWidth() != 0) {
@@ -291,14 +301,6 @@
         mousePos = e.getPoint();
         drawStartPos = mousePos;
-        if (ToolSettings.Shape.CIRCLE.equals(ToolSettings.getShape())) {
-            building.setBase(latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y)));
-        } else {
-            Node n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
-            if (n == null) {
-                building.setBase(latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y)));
-            } else {
-                building.setBase(n);
-            }
-        }
+        EastNorth en = getEastNorth();
+        building.setBase(en);
         mode = Mode.Drawing;
         updateStatusLine();
@@ -385,14 +387,21 @@
             return;
         Node n = null;
-        if (!ctrl)
-            n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
-        if (n != null) {
-            setCursor(cursorJoinNode);
-        } else {
-            if (customCursor != null && (!ctrl || isRectDrawing()))
-                setCursor(customCursor);
-            else
-                setCursor(getCursor());
-        }
+        if (!ctrl) {
+            n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isSelectable);
+            if (n != null) {
+                setCursor(cursorJoinNode);
+                return;
+            } else {
+                Way w = MainApplication.getMap().mapView.getNearestWay(mousePos, OsmPrimitive::isSelectable);
+                if (w != null && w.get("building") != null) {
+                    setCursor(cursorJoinWay);
+                    return;
+                }
+            }
+        }
+        if (customCursor != null && (!ctrl || isRectDrawing()))
+            setCursor(customCursor);
+        else
+            setCursor(getCursor());
 
     }
