source: osm/applications/editors/josm/plugins/utilsplugin/src/UtilsPlugin/MergeNodesAction.java@ 5080

Last change on this file since 5080 was 5080, checked in by gabriel, 17 years ago

utilsplugin: fix merge-nodes action

File size: 3.5 KB
Line 
1package UtilsPlugin;
2
3import static org.openstreetmap.josm.tools.I18n.tr;
4
5import java.util.ArrayList;
6import java.util.HashSet;
7import java.util.LinkedList;
8import java.util.Collection;
9import java.util.Collections;
10
11import java.awt.event.ActionEvent;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.data.osm.OsmPrimitive;
15import org.openstreetmap.josm.data.osm.Node;
16import org.openstreetmap.josm.data.osm.Way;
17import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
18import org.openstreetmap.josm.data.coor.EastNorth;
19import org.openstreetmap.josm.gui.MapFrame;
20import org.openstreetmap.josm.plugins.Plugin;
21import org.openstreetmap.josm.actions.JosmAction;
22import org.openstreetmap.josm.command.Command;
23import org.openstreetmap.josm.command.AddCommand;
24import org.openstreetmap.josm.command.DeleteCommand;
25import org.openstreetmap.josm.command.ChangeCommand;
26import org.openstreetmap.josm.command.SequenceCommand;
27
28import javax.swing.AbstractAction;
29import javax.swing.JOptionPane;
30
31class MergeNodesAction extends JosmAction {
32 public MergeNodesAction() {
33 super(tr("Merge nodes"), "mergenodes",
34 tr("Merge nodes"), 0, 0, true);
35 }
36
37 public void actionPerformed(ActionEvent e) {
38 Collection<OsmPrimitive> sel = Main.ds.getSelected();
39 HashSet<Node> nodes = new HashSet<Node>();
40
41 for (OsmPrimitive osm : sel)
42 if (osm instanceof Node)
43 nodes.add((Node)osm);
44 if (nodes.size() < 2) {
45 JOptionPane.showMessageDialog(Main.parent,
46 tr("Must select at least two nodes."));
47 return;
48 }
49
50 // Find the node with the lowest ID.
51 // We're gonna keep our 3-digit node ids.
52 Node target = null;
53 for (Node n : nodes) {
54 if (target == null || target.id == 0 || n.id < target.id) {
55 target = n;
56 }
57 }
58
59 Collection<Command> cmds = new LinkedList<Command>();
60
61 Node newTarget = new Node(target);
62
63 // Don't place the merged node on one of the former nodes.
64 // Place it right there in the middle.
65 double x = 0, y = 0;
66 for (Node n : nodes) {
67 x += n.eastNorth.east();
68 y += n.eastNorth.north();
69 }
70 newTarget.eastNorth = new EastNorth(
71 x / nodes.size(), y / nodes.size());
72
73 cmds.add(new ChangeCommand(target, newTarget));
74
75 HashSet<Node> delNodes = new HashSet<Node>(nodes);
76 delNodes.remove(target);
77 cmds.add(new DeleteCommand(delNodes));
78
79 for (Way w : Main.ds.ways) {
80 if (w.deleted || w.incomplete) continue;
81
82 boolean affected = false;
83 for (Node n : nodes) {
84 if (w.nodes.contains(n)) {
85 affected = true;
86 break;
87 }
88 }
89 if (!affected) continue;
90
91 // Replace the old nodes with the merged one
92 Way wnew = new Way(w);
93 for (int i = 0; i < wnew.nodes.size(); i++) {
94 if (nodes.contains(wnew.nodes.get(i))) {
95 wnew.nodes.set(i, target);
96 }
97 }
98
99 // Remove duplicates
100 Node lastN = null;
101 for (int i = wnew.nodes.size() - 1; i >= 0; i--) {
102 Node n = wnew.nodes.get(i);
103 if (lastN == n) wnew.nodes.remove(i);
104 lastN = n;
105 }
106
107 if (wnew.nodes.size() < 2) {
108 CollectBackReferencesVisitor backRefV =
109 new CollectBackReferencesVisitor(Main.ds, false);
110 backRefV.visit(w);
111 if (!backRefV.data.isEmpty()) {
112 JOptionPane.showMessageDialog(Main.parent,
113 tr("Cannot merge nodes: " +
114 "Would have to delete a way that is still used."));
115 return;
116 }
117
118 cmds.add(new DeleteCommand(Collections.singleton(w)));
119 } else {
120 cmds.add(new ChangeCommand(w, wnew));
121 }
122 }
123
124 Main.main.undoRedo.add(new SequenceCommand(tr("Merge Nodes"), cmds));
125 Main.ds.setSelected(newTarget);
126 Main.map.repaint();
127 }
128}
Note: See TracBrowser for help on using the repository browser.