Changeset 15428 in josm


Ignore:
Timestamp:
2019-10-06T11:41:29+02:00 (8 months ago)
Author:
GerdP
Message:

fix #18189 (18189-v3.patch)

Location:
trunk
Files:
7 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java

    r14397 r15428  
    1212import java.util.Comparator;
    1313import java.util.HashMap;
     14import java.util.HashSet;
    1415import java.util.LinkedList;
    1516import java.util.List;
    1617import java.util.Map;
    1718import java.util.Set;
    18 import java.util.SortedSet;
    19 import java.util.TreeSet;
     19
     20import javax.swing.JOptionPane;
    2021
    2122import org.openstreetmap.josm.command.ChangeCommand;
     
    3334import org.openstreetmap.josm.gui.MainApplication;
    3435import org.openstreetmap.josm.gui.MapView;
     36import org.openstreetmap.josm.gui.Notification;
    3537import org.openstreetmap.josm.tools.Geometry;
    3638import org.openstreetmap.josm.tools.MultiMap;
     
    98100        for (Node node : selectedNodes) {
    99101            List<WaySegment> wss = mapView.getNearestWaySegments(mapView.getPoint(node), OsmPrimitive::isSelectable);
    100             MultiMap<Way, Integer> insertPoints = new MultiMap<>();
     102            Set<Way> seenWays = new HashSet<>();
    101103            for (WaySegment ws : wss) {
    102104                // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive.
     
    104106                    continue;
    105107                }
    106 
    107                 if (!ws.getFirstNode().equals(node) && !ws.getSecondNode().equals(node)) {
    108                     insertPoints.put(ws.way, ws.lowerIndex);
     108                // only use the closest WaySegment of each way and ignore those that already contain the node
     109                if (!ws.getFirstNode().equals(node) && !ws.getSecondNode().equals(node)
     110                        && !seenWays.contains(ws.way)) {
     111                    MultiMap<Integer, Node> innerMap = data.get(ws.way);
     112                    if (innerMap == null) {
     113                        innerMap = new MultiMap<>();
     114                        data.put(ws.way, innerMap);
     115                    }
     116                    innerMap.put(ws.lowerIndex, node);
     117                    seenWays.add(ws.way);
    109118                }
    110119            }
    111             for (Map.Entry<Way, Set<Integer>> entry : insertPoints.entrySet()) {
    112                 final Way w = entry.getKey();
    113                 final Set<Integer> insertPointsForWay = entry.getValue();
    114                 for (int i : pruneSuccs(insertPointsForWay)) {
    115                     MultiMap<Integer, Node> innerMap;
    116                     if (!data.containsKey(w)) {
    117                         innerMap = new MultiMap<>();
    118                     } else {
    119                         innerMap = data.get(w);
    120                     }
    121                     innerMap.put(i, node);
    122                     data.put(w, innerMap);
    123                 }
    124             }
    125120        }
    126121
    127122        // Execute phase: traverse the structure "data" and finally put the nodes into place
     123        Map<Node, EastNorth> movedNodes = new HashMap<>();
    128124        for (Map.Entry<Way, MultiMap<Integer, Node>> entry : data.entrySet()) {
    129125            final Way w = entry.getKey();
     
    143139                                w.getNode(segmentIndex+1).getEastNorth(),
    144140                                node.getEastNorth());
    145                         MoveCommand c = new MoveCommand(
    146                                 node, ProjectionRegistry.getProjection().eastNorth2latlon(newPosition));
    147                         // Avoid moving a given node several times at the same position in case of overlapping ways
    148                         if (!cmds.contains(c)) {
    149                             cmds.add(c);
     141                        EastNorth prevMove = movedNodes.get(node);
     142                        if (prevMove != null) {
     143                            if (!prevMove.equalsEpsilon(newPosition, 1e-4)) {
     144                                new Notification(tr("Multiple target ways, no common point found. Nothing was changed."))
     145                                        .setIcon(JOptionPane.INFORMATION_MESSAGE)
     146                                        .show();
     147                                return;
     148                            }
     149                            continue;
    150150                        }
     151                        MoveCommand c = new MoveCommand(node,
     152                                ProjectionRegistry.getProjection().eastNorth2latlon(newPosition));
     153                        cmds.add(c);
     154                        movedNodes.put(node, newPosition);
    151155                    }
    152156                }
     
    166170    }
    167171
    168     private static SortedSet<Integer> pruneSuccs(Collection<Integer> is) {
    169         SortedSet<Integer> is2 = new TreeSet<>();
    170         for (int i : is) {
    171             if (!is2.contains(i - 1) && !is2.contains(i + 1)) {
    172                 is2.add(i);
    173             }
    174         }
    175         return is2;
    176     }
    177 
    178172    /**
    179173     * Sorts collinear nodes by their distance to a common reference node.
Note: See TracChangeset for help on using the changeset viewer.