Ticket #7164: 0002-Make-followline-to-handle-wraps-and-stop-at-ambiguit.patch

File 0002-Make-followline-to-handle-wraps-and-stop-at-ambiguit.patch, 6.2 KB (added by ij, 13 years ago)

0002-Make-followline-to-handle-wraps-and-stop-at-ambiguit.patch

  • src/org/openstreetmap/josm/actions/FollowLineAction.java

    From 3f4a6e1b587b3fee55ad0dcc8c48b8edea8ad886 Mon Sep 17 00:00:00 2001
    From: =?utf-8?q?Ilpo=20J=C3=A4rvinen?= <ilpo.jarvinen@helsinki.fi>
    Date: Sun, 18 Dec 2011 02:58:07 +0200
    Subject: [PATCH 2/2] Make followline to handle wraps and stop at ambiguities
    
    When the toFollow way is closed and wraps, the code only
    worked for one direction. I first came across very complicated
    fix using the existing code, but then decided to make the
    code logic followable to mortals too. While recoding, also
    another issue was easy to fix, namely, the followline previously
    picked just any suitable extension that if found. Instead,
    make it to stop when first ambiguity is encountered forcing
    the user to point to which direction the way should be extended.
    ---
     .../josm/actions/FollowLineAction.java             |   62 +++++++++-----------
     src/org/openstreetmap/josm/data/osm/Way.java       |   25 ++++++++
     2 files changed, 53 insertions(+), 34 deletions(-)
    
    diff --git a/src/org/openstreetmap/josm/actions/FollowLineAction.java b/src/org/openstreetmap/josm/actions/FollowLineAction.java
    index 58fe454..6fbffec 100644
    a b import java.awt.event.KeyEvent;  
    88import java.util.Collection;
    99import java.util.Iterator;
    1010import java.util.List;
     11import java.util.Set;
    1112
    1213import org.openstreetmap.josm.Main;
    1314import org.openstreetmap.josm.actions.mapmode.DrawAction;
    public class FollowLineAction extends JosmAction {  
    8283        List<OsmPrimitive> referrers = last.getReferrers();
    8384        if (referrers.size() < 2) return; // There's nothing to follow
    8485       
     86        Node newPoint = null;       
    8587        Iterator<OsmPrimitive> i = referrers.iterator();
    8688        while (i.hasNext()) {
    8789            OsmPrimitive referrer = i.next();
    public class FollowLineAction extends JosmAction {  
    9294            if (toFollow.equals(follower)) {
    9395                continue;
    9496            }
    95             List<Node> points = toFollow.getNodes();
    96             int indexOfLast = points.indexOf(last);
    97             int indexOfPrev = points.indexOf(prev);
    98             if ((indexOfLast == -1) || (indexOfPrev == -1)) { // Both points must belong to both lines
     97            Set<Node> points = toFollow.getNeighbours(last);
     98            if (!points.remove(prev) || (points.size() == 0))
    9999                continue;
    100             }
    101             if (Math.abs(indexOfPrev - indexOfLast) != 1) {  // ...and be consecutive
    102                 continue;
    103             }
    104             Node newPoint = null;
    105             if (indexOfPrev == (indexOfLast - 1)) {
    106                 if ((indexOfLast + 1) < points.size()) {
    107                     newPoint = points.get(indexOfLast + 1);
    108                 }
    109             } else {
    110                 if ((indexOfLast - 1) >= 0) {
    111                     newPoint = points.get(indexOfLast - 1);
    112                 }
    113             }
    114             if (newPoint != null) {
    115                 Way newFollower = new Way(follower);
    116                 if (reversed) {
    117                     newFollower.addNode(0, newPoint);
    118                 } else {
    119                     newFollower.addNode(newPoint);
    120                 }
    121                 Main.main.undoRedo.add(new ChangeCommand(follower, newFollower));
    122                 osmLayer.data.clearSelection();
    123                 osmLayer.data.addSelected(newFollower);
    124                 osmLayer.data.addSelected(newPoint);
    125                 // "viewport following" mode for tracing long features
    126                 // from aerial imagery or GPS tracks.
    127                 if (Main.map.mapView.viewportFollowing) {
    128                     Main.map.mapView.smoothScrollTo(newPoint.getEastNorth());
    129                 };
     100            if (points.size() > 1)    // Ambiguous junction?
    130101                return;
     102
     103            Node newPointCandidate = points.iterator().next();
     104
     105            if ((newPoint != null) && (newPoint != newPointCandidate))
     106                return;         // Ambiguous junction, force to select next
     107
     108            newPoint = newPointCandidate;
     109        }
     110        if (newPoint != null) {
     111            Way newFollower = new Way(follower);
     112            if (reversed) {
     113                newFollower.addNode(0, newPoint);
     114            } else {
     115                newFollower.addNode(newPoint);
    131116            }
     117            Main.main.undoRedo.add(new ChangeCommand(follower, newFollower));
     118            osmLayer.data.clearSelection();
     119            osmLayer.data.addSelected(newFollower);
     120            osmLayer.data.addSelected(newPoint);
     121            // "viewport following" mode for tracing long features
     122            // from aerial imagery or GPS tracks.
     123            if (Main.map.mapView.viewportFollowing) {
     124                Main.map.mapView.smoothScrollTo(newPoint.getEastNorth());
     125            };
    132126        }
    133127    }
    134128}
  • src/org/openstreetmap/josm/data/osm/Way.java

    diff --git a/src/org/openstreetmap/josm/data/osm/Way.java b/src/org/openstreetmap/josm/data/osm/Way.java
    index 8336bc4..137fbc4 100644
    a b import java.util.ArrayList;  
    77import java.util.Arrays;
    88import java.util.List;
    99import java.util.Set;
     10import java.util.HashSet;
    1011
    1112import org.openstreetmap.josm.Main;
    1213import org.openstreetmap.josm.data.coor.LatLon;
    public final class Way extends OsmPrimitive implements IWay {  
    138139        return false;
    139140    }
    140141
     142    /**
     143     * Return nodes adjacent to <code>node</code>
     144     *
     145     * @param node the node. May be null.
     146     * @return Set of nodes adjacent to <code>node</code>
     147     * @since 4666
     148     */
     149    public Set<Node> getNeighbours(Node node) {
     150        HashSet<Node> neigh = new HashSet<Node>();
     151
     152        if (node == null) return neigh;
     153
     154        Node[] nodes = this.nodes;
     155        for (int i=0; i<nodes.length; i++) {
     156            if (nodes[i].equals(node)) {
     157                if (i > 0)
     158                    neigh.add(nodes[i-1]);
     159                if (i < nodes.length-1)
     160                    neigh.add(nodes[i+1]);
     161            }
     162        }
     163        return neigh;
     164    }
     165
    141166    public List<Pair<Node,Node>> getNodePairs(boolean sort) {
    142167        List<Pair<Node,Node>> chunkSet = new ArrayList<Pair<Node,Node>>();
    143168        if (isIncomplete()) return chunkSet;