Index: trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
===================================================================
--- trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 18467)
+++ trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java	(revision 18468)
@@ -725,7 +725,30 @@
                 MoveCommand moveCmd = null;
                 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {
+                    EastNorth clampedEastNorth = currentEN;
+                    if (platformMenuShortcutKeyMask) {
+                        Way w = ds.getLastSelectedWay();
+                        if (w != null && w.getNodesCount() == 2) {
+                            double clamph = w.firstNode().getEastNorth().heading(w.lastNode().getEastNorth());
+                            double dh = startEN.heading(currentEN, clamph);
+                            switch ((int) (dh / (Math.PI/4))) {
+                            case 1:
+                            case 2:
+                                dh -= Math.PI/2;
+                                break;
+                            case 3:
+                            case 4:
+                                dh += Math.PI;
+                                break;
+                            case 5:
+                            case 6:
+                                dh += Math.PI/2;
+                                break;
+                            }
+                            clampedEastNorth = currentEN.rotate(startEN, -dh);
+                        }
+                    }
                     moveCmd = (MoveCommand) c;
                     moveCmd.saveCheckpoint();
-                    moveCmd.applyVectorTo(currentEN);
+                    moveCmd.applyVectorTo(clampedEastNorth);
                 } else if (!selection.isEmpty()) {
                     moveCmd = new MoveCommand(selection, startEN, currentEN);
Index: trunk/src/org/openstreetmap/josm/data/coor/EastNorth.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/coor/EastNorth.java	(revision 18467)
+++ trunk/src/org/openstreetmap/josm/data/coor/EastNorth.java	(revision 18468)
@@ -142,4 +142,22 @@
     public double heading(EastNorth other) {
         double hd = Math.atan2(other.east() - east(), other.north() - north());
+        if (hd < 0) {
+            hd = 2 * Math.PI + hd;
+        }
+        return hd;
+    }
+
+    /**
+     * Behaves exactly like {@link EastNorth#heading(EastNorth)} if {@code refHeading} is {@code 0.0},
+     * otherwise gives a heading not relative to north (0.0).  It replies the radians needed to add to
+     * {@code refHeading} to get from this EastNorth to another.
+     * @param other the "destination" position
+     * @param refHeading origin ("false" north if different from {@code 0.0})
+     * @return heading with respect to {@code refHeading} as origin
+     * @since 18468
+     */
+    public double heading(EastNorth other, double refHeading) {
+        double hd = heading(other);
+        hd -= refHeading;
         if (hd < 0) {
             hd = 2 * Math.PI + hd;
Index: trunk/src/org/openstreetmap/josm/data/osm/DataSet.java
===================================================================
--- trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 18467)
+++ trunk/src/org/openstreetmap/josm/data/osm/DataSet.java	(revision 18468)
@@ -601,4 +601,15 @@
     }
 
+    /**
+     * Returns the way selected last or null if no way primitives were selected or selection is empty.
+     * @return last way in selection or null
+     * @since 18468
+     */
+    public Way getLastSelectedWay() {
+        Way lastWay = null;
+        for (Way way: getSelectedWays()) lastWay = way;
+        return lastWay;
+    }
+
     @Override
     public Collection<WaySegment> getHighlightedVirtualNodes() {
