Ticket #5133: 0001-Action-to-disconnect-nodes-from-ways.patch

File 0001-Action-to-disconnect-nodes-from-ways.patch, 9.5 KB (added by giuseppe.bilotta@…, 11 years ago)

Patch to implement the feature

  • new file 2001

    From 6aafda8d07eec1895f1e3e580dca8ab42ba0ded4 Mon Sep 17 00:00:00 2001
    From: Giuseppe Bilotta <giuseppe.bilotta@gmail.com>
    Date: Mon, 29 Jul 2013 08:29:30 +0200
    Subject: [PATCH] Action to disconnect nodes from ways
    
    ---
     images/unjoinnodeway.png                           | Bin 0 -> 385 bytes
     .../josm/actions/UnJoinNodeWayAction.java          | 158 +++++++++++++++++++++
     src/org/openstreetmap/josm/gui/MainMenu.java       |   3 +
     3 files changed, 161 insertions(+)
     create mode 100644 images/unjoinnodeway.png
     create mode 100644 src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java
    
    diff --git a/images/unjoinnodeway.png b/images/unjoinnodeway.png
    new file mode 100644
    index 0000000000000000000000000000000000000000..4179e6902577640d66deab6f78cab43c8b0a4786
    GIT binary patch
    literal 385
    zcmeAS@N?(olHy`uVBq!ia0vp^5+KaM1|%Pp+x`GjY)RhkE)4%caKYZ?lYt_f1s;*b
    z3=G`DAk4@xYYs>cdx@v7EBjq`Ssnvp>D3WU3=E8Xo-U3d9>?Ea-s{H{D8Tx_-@z~{
    zQbL-=Y@@jL+J&1w&#Y0FW4M3d$h{-1Nl7Lf4FegKvp1VZhPx;oS@AHWxc=Ns<Kp)p
    zOv7|H9x+*?<D`-oHu;T})$8@iElW0NEdT1~zxOitX|8JvOqjPf<X$oGu;iWdKtc5M
    zVwqjRvx1(<nF%};*nPvjr+7<Ym-UxjYj1rq@0fj6Wy+1*t1jt(rArDLPw$A#ea<8E
    zkjq~qN!|FXb4;?uTG!(h9;|K)&mVNy^}pkJPlmx9mUFvVb{fSO&gW7Q=Ha<y?WuN<
    zeM(XM>PdD13OpY_bvE99@ag*bi}z>$`QKZlmY48ZeUjL|S_|fFVharAyNW+4_gt>9
    cd3i{>Jl~Te!YJi0Ft8XrUHx3vIVCg!02-y3CIA2c
  • new file src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java

    literal 0
    HcmV?d00001
    
    diff --git a/src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java b/src/org/openstreetmap/josm/actions/UnJoinNodeWayAction.java
    new file mode 100644
    index 0000000..6ffd3ed
    - +  
     1//License: GPL. Copyright 2007 by Immanuel Scholz and others
     2package org.openstreetmap.josm.actions;
     3
     4import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
     5import static org.openstreetmap.josm.tools.I18n.tr;
     6import static org.openstreetmap.josm.tools.I18n.trn;
     7
     8import java.awt.event.ActionEvent;
     9import java.awt.event.KeyEvent;
     10import java.util.ArrayList;
     11import java.util.Collection;
     12import java.util.Collections;
     13import java.util.HashSet;
     14import java.util.Iterator;
     15import java.util.List;
     16
     17import javax.swing.JOptionPane;
     18
     19import org.openstreetmap.josm.Main;
     20import org.openstreetmap.josm.command.ChangeNodesCommand;
     21import org.openstreetmap.josm.command.Command;
     22import org.openstreetmap.josm.data.osm.Node;
     23import org.openstreetmap.josm.data.osm.OsmPrimitive;
     24import org.openstreetmap.josm.data.osm.Way;
     25import org.openstreetmap.josm.tools.Shortcut;
     26
     27public class UnJoinNodeWayAction extends JosmAction {
     28    public UnJoinNodeWayAction() {
     29        super(tr("Disconnect Node from Way"), "unjoinnodeway",
     30                tr("Disconnect nodes from a way they currently belong to"),
     31                Shortcut.registerShortcut("tools:unjoinnodeway",
     32                    tr("Tool: {0}", tr("Disconnect Node from Way")), KeyEvent.VK_J, Shortcut.ALT), true);
     33        putValue("help", ht("/Action/UnJoinNodeWay"));
     34    }
     35
     36    @Override
     37    public void actionPerformed(ActionEvent e) {
     38
     39        Collection<OsmPrimitive> selection = getCurrentDataSet().getSelected();
     40
     41        List<Node> selectedNodes = OsmPrimitive.getFilteredList(selection, Node.class);
     42        List<Way> selectedWays = OsmPrimitive.getFilteredList(selection, Way.class);
     43        List<Way> applicableWays = getApplicableWays(selectedWays, selectedNodes);
     44
     45        if (applicableWays == null) {
     46            JOptionPane.showMessageDialog(
     47                    Main.parent,
     48                    tr("Select at least a node to be disconnected."),
     49                    tr("Warning"),
     50                    JOptionPane.WARNING_MESSAGE);
     51            return;
     52        } else if (applicableWays.isEmpty()) {
     53            JOptionPane.showMessageDialog(Main.parent,
     54                    tr("The selected nodes do not share the same way."),
     55                    tr("Warning"),
     56                    JOptionPane.WARNING_MESSAGE);
     57            return;
     58        } else if (applicableWays.size() > 1) {
     59            JOptionPane.showMessageDialog(Main.parent,
     60                    trn("There is more than one way using the node you selected. Please select the way also.",
     61                            "There is more than one way using the nodes you selected. Please select the way also.",
     62                            selectedNodes.size()),
     63                            tr("Warning"),
     64                            JOptionPane.WARNING_MESSAGE);
     65            return;
     66        } else if (applicableWays.get(0).getRealNodesCount() < selectedNodes.size() + 2) {
     67            // there is only one affected way, but removing the selected nodes would only leave it
     68            // with less than 2 nodes
     69            JOptionPane.showMessageDialog(Main.parent,
     70                    trn("The affected way would disappear after removing the selected node.",
     71                        "The affected way would disappear after removing the selected nodes.",
     72                        selectedNodes.size()),
     73                    tr("Warning"),
     74                    JOptionPane.WARNING_MESSAGE);
     75            return;
     76        }
     77
     78        // Finally, applicableWays contains only one perfect way
     79        Way selectedWay = applicableWays.get(0);
     80        List<Node> otherNodes = selectedWay.getNodes();
     81        otherNodes.removeAll(selectedNodes);
     82        Main.main.undoRedo.add(new ChangeNodesCommand(selectedWay, otherNodes));
     83        Main.map.repaint();
     84    }
     85
     86    // shamefully copied over from SplitWayAction
     87    private List<Way> getApplicableWays(List<Way> selectedWays, List<Node> selectedNodes) {
     88        if (selectedNodes.isEmpty())
     89            return null;
     90
     91        // Special case - one of the selected ways touches (not cross) way that we want to split
     92        if (selectedNodes.size() == 1) {
     93            Node n = selectedNodes.get(0);
     94            List<Way> referedWays = OsmPrimitive.getFilteredList(n.getReferrers(), Way.class);
     95            Way inTheMiddle = null;
     96            boolean foundSelected = false;
     97            for (Way w: referedWays) {
     98                if (selectedWays.contains(w)) {
     99                    foundSelected = true;
     100                }
     101                if (w.getNode(0) != n && w.getNode(w.getNodesCount() - 1) != n) {
     102                    if (inTheMiddle == null) {
     103                        inTheMiddle = w;
     104                    } else {
     105                        inTheMiddle = null;
     106                        break;
     107                    }
     108                }
     109            }
     110            if (foundSelected && inTheMiddle != null)
     111                return Collections.singletonList(inTheMiddle);
     112        }
     113
     114        // List of ways shared by all nodes
     115        List<Way> result = new ArrayList<Way>(OsmPrimitive.getFilteredList(selectedNodes.get(0).getReferrers(), Way.class));
     116        for (int i=1; i<selectedNodes.size(); i++) {
     117            List<OsmPrimitive> ref = selectedNodes.get(i).getReferrers();
     118            for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     119                if (!ref.contains(it.next())) {
     120                    it.remove();
     121                }
     122            }
     123        }
     124
     125        // Remove broken ways
     126        for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     127            if (it.next().getNodesCount() <= 2) {
     128                it.remove();
     129            }
     130        }
     131
     132        if (selectedWays.isEmpty())
     133            return result;
     134        else {
     135            // Return only selected ways
     136            for (Iterator<Way> it = result.iterator(); it.hasNext(); ) {
     137                if (!selectedWays.contains(it.next())) {
     138                    it.remove();
     139                }
     140            }
     141            return result;
     142        }
     143    }
     144
     145    @Override
     146    protected void updateEnabledState() {
     147        if (getCurrentDataSet() == null) {
     148            setEnabled(false);
     149        } else {
     150            updateEnabledState(getCurrentDataSet().getSelected());
     151        }
     152    }
     153
     154    @Override
     155    protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
     156        setEnabled(selection != null && !selection.isEmpty());
     157    }
     158}
  • src/org/openstreetmap/josm/gui/MainMenu.java

    diff --git a/src/org/openstreetmap/josm/gui/MainMenu.java b/src/org/openstreetmap/josm/gui/MainMenu.java
    index 196e16e..dc75be8 100644
    a b import org.openstreetmap.josm.actions.SimplifyWayAction;  
    8484import org.openstreetmap.josm.actions.SplitWayAction;
    8585import org.openstreetmap.josm.actions.ToggleGPXLinesAction;
    8686import org.openstreetmap.josm.actions.UnGlueAction;
     87import org.openstreetmap.josm.actions.UnJoinNodeWayAction;
    8788import org.openstreetmap.josm.actions.UndoAction;
    8889import org.openstreetmap.josm.actions.UnselectAllAction;
    8990import org.openstreetmap.josm.actions.UpdateDataAction;
    public class MainMenu extends JMenuBar {  
    185186    public final JosmAction createCircle = new CreateCircleAction();
    186187    public final JosmAction mergeNodes = new MergeNodesAction();
    187188    public final JosmAction joinNodeWay = new JoinNodeWayAction();
     189    public final JosmAction unJoinNodeWay = new UnJoinNodeWayAction();
    188190    public final JosmAction unglueNodes = new UnGlueAction();
    189191    public final JosmAction simplifyWay = new SimplifyWayAction();
    190192    public final JosmAction joinAreas = new JoinAreasAction();
    public class MainMenu extends JMenuBar {  
    603605        toolsMenu.addSeparator();
    604606        add(toolsMenu, mergeNodes);
    605607        add(toolsMenu, joinNodeWay);
     608        add(toolsMenu, unJoinNodeWay);
    606609        add(toolsMenu, unglueNodes);
    607610        toolsMenu.addSeparator();
    608611        add(toolsMenu, joinAreas);