Index: src/org/openstreetmap/josm/plugins/buildings_tools/Building.java
===================================================================
--- src/org/openstreetmap/josm/plugins/buildings_tools/Building.java	(revision 34722)
+++ src/org/openstreetmap/josm/plugins/buildings_tools/Building.java	(working copy)
@@ -12,9 +12,11 @@
 import java.util.Arrays;
 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;
 
@@ -26,7 +28,6 @@
 import org.openstreetmap.josm.command.SequenceCommand;
 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;
 import org.openstreetmap.josm.data.osm.Node;
@@ -230,20 +231,8 @@
     }
 
     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;
+        return mv.getNearestNode(mv.getPoint(pos), OsmPrimitive::isSelectable);
     }
 
     /**
@@ -403,26 +392,24 @@
 
         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();
+            // 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) {
-                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));
+                Way w2 = mv.getNearestWay(mv.getPoint(n), OsmPrimitive::isSelectable);
+                if (w2 != null && w2.get("building") != null)
+                    others.add(w2);
             }
-            // 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);
+                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), maxDist);
+                snapToWay(otherNodes, Arrays.asList(nodes));
                 if (otherNodes.size() != other.getNodesCount()) {
                     Way newWay = new Way(other);
                     newWay.setNodes(otherNodes);
@@ -436,18 +423,18 @@
     }
 
     /**
-     * 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
      *            List of nodes that might be changed
      * @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) {
+        final double tolerance = MainApplication.getMap().mapView.getDist100Pixel() * 0.01
+                * MapView.PROP_SNAP_DISTANCE.get();
+
         for (int i = 0; i < wayNodes.size(); i++) {
             Node n0 = wayNodes.get(i);
             Node n1 = wayNodes.get(i + 1 == wayNodes.size() ? 0 : i + 1);
@@ -454,12 +441,11 @@
             for (Node n2 : otherNodes) {
                 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()) < 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: src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java
===================================================================
--- src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(revision 34722)
+++ src/org/openstreetmap/josm/plugins/buildings_tools/DrawBuildingAction.java	(working copy)
@@ -28,6 +28,7 @@
 import org.openstreetmap.josm.data.osm.Node;
 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;
 import org.openstreetmap.josm.gui.MainApplication;
@@ -38,6 +39,7 @@
 import org.openstreetmap.josm.gui.layer.OsmDataLayer;
 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;
 import org.openstreetmap.josm.tools.Shortcut;
@@ -50,6 +52,7 @@
 
     private final Cursor cursorCrosshair;
     private final Cursor cursorJoinNode;
+    private final Cursor cursorJoinWay;
     private Cursor currCursor;
     private Cursor customCursor;
 
@@ -71,6 +74,7 @@
 
         cursorCrosshair = getCursor();
         cursorJoinNode = ImageProvider.getCursor("crosshair", "joinnode");
+        cursorJoinWay = ImageProvider.getCursor("crosshair", "joinway");
         currCursor = cursorCrosshair;
     }
 
@@ -200,17 +204,23 @@
     }
 
     private EastNorth getEastNorth() {
-        Node n;
-        if (ctrl) {
-            n = null;
-        } else {
-            n = MainApplication.getMap().mapView.getNearestNode(mousePos, OsmPrimitive::isUsable);
+        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;
+                }
+            }
         }
-        if (n == null) {
-            return latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y));
-        } else {
-            return latlon2eastNorth(n.getCoor());
-        }
+        return latlon2eastNorth(MainApplication.getMap().mapView.getLatLon(mousePos.x, mousePos.y));
     }
 
     private boolean isRectDrawing() {
@@ -293,12 +303,7 @@
         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);
-            }
+            building.setBase(getEastNorth());
         }
         mode = Mode.Drawing;
         updateStatusLine();
@@ -384,16 +389,23 @@
         if (!MainApplication.isDisplayingMapView())
             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());
 
     }
 
