1 | package UtilsPlugin;
|
---|
2 |
|
---|
3 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
4 |
|
---|
5 | import java.util.ArrayList;
|
---|
6 | import java.util.HashSet;
|
---|
7 | import java.util.LinkedList;
|
---|
8 | import java.util.Collection;
|
---|
9 | import java.util.Collections;
|
---|
10 |
|
---|
11 | import java.awt.event.ActionEvent;
|
---|
12 |
|
---|
13 | import org.openstreetmap.josm.Main;
|
---|
14 | import org.openstreetmap.josm.data.osm.OsmPrimitive;
|
---|
15 | import org.openstreetmap.josm.data.osm.Node;
|
---|
16 | import org.openstreetmap.josm.data.osm.Way;
|
---|
17 | import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor;
|
---|
18 | import org.openstreetmap.josm.data.coor.EastNorth;
|
---|
19 | import org.openstreetmap.josm.gui.MapFrame;
|
---|
20 | import org.openstreetmap.josm.plugins.Plugin;
|
---|
21 | import org.openstreetmap.josm.actions.JosmAction;
|
---|
22 | import org.openstreetmap.josm.command.Command;
|
---|
23 | import org.openstreetmap.josm.command.AddCommand;
|
---|
24 | import org.openstreetmap.josm.command.DeleteCommand;
|
---|
25 | import org.openstreetmap.josm.command.ChangeCommand;
|
---|
26 | import org.openstreetmap.josm.command.SequenceCommand;
|
---|
27 |
|
---|
28 | import javax.swing.AbstractAction;
|
---|
29 | import javax.swing.JOptionPane;
|
---|
30 |
|
---|
31 | class 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 | }
|
---|