Changeset 7131 in josm


Ignore:
Timestamp:
2014-05-15T00:56:35+02:00 (10 years ago)
Author:
simon04
Message:

fix #4550 - Add a "Move Node onto Way" action (opposite of "Join Node to Way")

Location:
trunk
Files:
1 added
2 edited

Legend:

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

    r7005 r7131  
    11//License: GPL. For details, see LICENSE file.
    22package org.openstreetmap.josm.actions;
     3
     4import org.openstreetmap.josm.Main;
     5import org.openstreetmap.josm.command.ChangeCommand;
     6import org.openstreetmap.josm.command.Command;
     7import org.openstreetmap.josm.command.MoveCommand;
     8import org.openstreetmap.josm.command.SequenceCommand;
     9import org.openstreetmap.josm.data.coor.EastNorth;
     10import org.openstreetmap.josm.data.osm.Node;
     11import org.openstreetmap.josm.data.osm.OsmPrimitive;
     12import org.openstreetmap.josm.data.osm.Way;
     13import org.openstreetmap.josm.data.osm.WaySegment;
     14import org.openstreetmap.josm.data.projection.Projections;
     15import org.openstreetmap.josm.tools.Geometry;
     16import org.openstreetmap.josm.tools.MultiMap;
     17import org.openstreetmap.josm.tools.Shortcut;
     18
     19import java.awt.event.ActionEvent;
     20import java.awt.event.KeyEvent;
     21import java.util.Collection;
     22import java.util.Collections;
     23import java.util.LinkedList;
     24import java.util.List;
     25import java.util.Map;
     26import java.util.Set;
     27import java.util.SortedSet;
     28import java.util.TreeSet;
    329
    430import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
    531import static org.openstreetmap.josm.tools.I18n.tr;
    632
    7 import java.awt.event.ActionEvent;
    8 import java.awt.event.KeyEvent;
    9 import java.util.ArrayList;
    10 import java.util.Collection;
    11 import java.util.Collections;
    12 import java.util.HashMap;
    13 import java.util.HashSet;
    14 import java.util.LinkedList;
    15 import java.util.List;
    16 import java.util.Map;
    17 
    18 import org.openstreetmap.josm.Main;
    19 import org.openstreetmap.josm.command.ChangeCommand;
    20 import org.openstreetmap.josm.command.Command;
    21 import org.openstreetmap.josm.command.SequenceCommand;
    22 import org.openstreetmap.josm.data.osm.Node;
    23 import org.openstreetmap.josm.data.osm.OsmPrimitive;
    24 import org.openstreetmap.josm.data.osm.Way;
    25 import org.openstreetmap.josm.data.osm.WaySegment;
    26 import org.openstreetmap.josm.tools.Shortcut;
    27 
    2833public class JoinNodeWayAction extends JosmAction {
    2934
     35    protected final boolean joinWayToNode;
     36
     37    protected JoinNodeWayAction(boolean joinWayToNode, String name, String iconName, String tooltip, Shortcut shortcut, boolean registerInToolbar) {
     38        super(name, iconName, tooltip, shortcut, registerInToolbar);
     39        this.joinWayToNode = joinWayToNode;
     40    }
     41
    3042    /**
    31      * Constructs a new {@code JoinNodeWayAction}.
     43     * Constructs a Join Node to Way action.
    3244     */
    33     public JoinNodeWayAction() {
    34         super(tr("Join Node to Way"), "joinnodeway", tr("Include a node into the nearest way segments"),
     45    public static JoinNodeWayAction createJoinNodeToWayAction() {
     46        JoinNodeWayAction action = new JoinNodeWayAction(false,
     47                tr("Join Node to Way"), "joinnodeway", tr("Include a node into the nearest way segments"),
    3548                Shortcut.registerShortcut("tools:joinnodeway", tr("Tool: {0}", tr("Join Node to Way")), KeyEvent.VK_J, Shortcut.DIRECT), true);
    36         putValue("help", ht("/Action/JoinNodeWay"));
     49        action.putValue("help", ht("/Action/JoinNodeWay"));
     50        return action;
     51    }
     52
     53    /**
     54     * Constructs a Move Node onto Way action.
     55     */
     56    public static JoinNodeWayAction createMoveNodeOntoWayAction() {
     57        JoinNodeWayAction action = new JoinNodeWayAction(true,
     58                tr("Move Node onto Way"), "movewayontonode", tr("Move the node onto the nearest way segments and include it"),
     59                null, true);
     60        return action;
    3761    }
    3862
     
    4569        if (selectedNodes.size() != 1) return;
    4670
    47         Node node = selectedNodes.iterator().next();
     71        final Node node = selectedNodes.iterator().next();
    4872
    4973        Collection<Command> cmds = new LinkedList<>();
     
    5377                !getCurrentDataSet().getSelectedWays().isEmpty();
    5478
    55             List<WaySegment> wss = Main.map.mapView.getNearestWaySegments(
    56                     Main.map.mapView.getPoint(node), OsmPrimitive.isSelectablePredicate);
    57             HashMap<Way, List<Integer>> insertPoints = new HashMap<>();
    58             for (WaySegment ws : wss) {
    59                 // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive.
    60                 if(restrictToSelectedWays && !ws.way.isSelected()) {
    61                     continue;
    62                 }
    63 
    64                 List<Integer> is;
    65                 if (insertPoints.containsKey(ws.way)) {
    66                     is = insertPoints.get(ws.way);
    67                 } else {
    68                     is = new ArrayList<>();
    69                     insertPoints.put(ws.way, is);
    70                 }
    71 
    72                 if (ws.way.getNode(ws.lowerIndex) != node
    73                         && ws.way.getNode(ws.lowerIndex+1) != node) {
    74                     is.add(ws.lowerIndex);
    75                 }
     79        List<WaySegment> wss = Main.map.mapView.getNearestWaySegments(
     80                Main.map.mapView.getPoint(node), OsmPrimitive.isSelectablePredicate);
     81        MultiMap<Way, Integer> insertPoints = new MultiMap<>();
     82        for (WaySegment ws : wss) {
     83            // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive.
     84            if (restrictToSelectedWays && !ws.way.isSelected()) {
     85                continue;
    7686            }
    7787
    78             for (Map.Entry<Way, List<Integer>> insertPoint : insertPoints.entrySet()) {
    79                 List<Integer> is = insertPoint.getValue();
    80                 if (is.isEmpty()) {
    81                     continue;
     88            if (ws.getFirstNode() != node && ws.getSecondNode() != node) {
     89                insertPoints.put(ws.way, ws.lowerIndex);
     90            }
     91        }
     92
     93        for (Map.Entry<Way, Set<Integer>> entry : insertPoints.entrySet()) {
     94            final Way w = entry.getKey();
     95            final Set<Integer> insertPointsForWay = entry.getValue();
     96            if (insertPointsForWay.isEmpty()) {
     97                continue;
     98            }
     99
     100            List<Node> nodesToAdd = w.getNodes();
     101            for (int i : pruneSuccsAndReverse(insertPointsForWay)) {
     102                if (joinWayToNode) {
     103                    EastNorth newPosition = Geometry.closestPointToSegment(
     104                            w.getNode(i).getEastNorth(), w.getNode(i + 1).getEastNorth(), node.getEastNorth());
     105                    cmds.add(new MoveCommand(node, Projections.inverseProject(newPosition)));
    82106                }
    83 
    84                 Way w = insertPoint.getKey();
    85                 List<Node> nodesToAdd = w.getNodes();
    86                 pruneSuccsAndReverse(is);
    87                 for (int i : is) {
    88                     nodesToAdd.add(i+1, node);
    89                 }
    90                 Way wnew = new Way(w);
    91                 wnew.setNodes(nodesToAdd);
    92                 cmds.add(new ChangeCommand(w, wnew));
     107                nodesToAdd.add(i + 1, node);
    93108            }
    94             if (cmds.isEmpty()) return;
    95             Main.main.undoRedo.add(new SequenceCommand(tr("Join Node and Line"), cmds));
    96             Main.map.repaint();
     109            Way wnew = new Way(w);
     110            wnew.setNodes(nodesToAdd);
     111            cmds.add(new ChangeCommand(w, wnew));
     112        }
     113        if (cmds.isEmpty()) return;
     114        Main.main.undoRedo.add(new SequenceCommand(getValue(NAME).toString(), cmds));
     115        Main.map.repaint();
    97116    }
    98117
    99     private static void pruneSuccsAndReverse(List<Integer> is) {
    100         HashSet<Integer> is2 = new HashSet<>();
     118    private static SortedSet<Integer> pruneSuccsAndReverse(Collection<Integer> is) {
     119        SortedSet<Integer> is2 = new TreeSet<>(Collections.reverseOrder());
    101120        for (int i : is) {
    102121            if (!is2.contains(i - 1) && !is2.contains(i + 1)) {
     
    104123            }
    105124        }
    106         is.clear();
    107         is.addAll(is2);
    108         Collections.sort(is);
    109         Collections.reverse(is);
     125        return is2;
    110126    }
    111127
  • trunk/src/org/openstreetmap/josm/gui/MainMenu.java

    r7075 r7131  
    248248    public final MergeNodesAction mergeNodes = new MergeNodesAction();
    249249    /** Tools / Join Node to Way */
    250     public final JoinNodeWayAction joinNodeWay = new JoinNodeWayAction();
     250    public final JoinNodeWayAction joinNodeWay = JoinNodeWayAction.createJoinNodeToWayAction();
     251    /** Tools / Join Way to Node */
     252    public final JoinNodeWayAction moveNodeOntoWay = JoinNodeWayAction.createMoveNodeOntoWayAction();
    251253    /** Tools / Disconnect Node from Way */
    252254    public final UnJoinNodeWayAction unJoinNodeWay = new UnJoinNodeWayAction();
     
    737739        add(toolsMenu, mergeNodes);
    738740        add(toolsMenu, joinNodeWay);
     741        add(toolsMenu, moveNodeOntoWay);
    739742        add(toolsMenu, unJoinNodeWay);
    740743        add(toolsMenu, unglueNodes);
Note: See TracChangeset for help on using the changeset viewer.