source: josm/trunk/src/org/openstreetmap/josm/actions/DistributeAction.java@ 1862

Last change on this file since 1862 was 1862, checked in by jttt, 15 years ago

Way refactoring - added method that will in future replace public field nodes

File size: 4.7 KB
Line 
1// License: GPL. Copyright 2009 by Immanuel Scholz and others
2package org.openstreetmap.josm.actions;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.awt.event.ActionEvent;
7import java.awt.event.KeyEvent;
8import java.util.Collection;
9import java.util.LinkedList;
10
11import javax.swing.JOptionPane;
12
13import org.openstreetmap.josm.Main;
14import org.openstreetmap.josm.command.Command;
15import org.openstreetmap.josm.command.MoveCommand;
16import org.openstreetmap.josm.command.SequenceCommand;
17import org.openstreetmap.josm.data.osm.Node;
18import org.openstreetmap.josm.data.osm.OsmPrimitive;
19import org.openstreetmap.josm.data.osm.Way;
20import org.openstreetmap.josm.gui.OptionPaneUtil;
21import org.openstreetmap.josm.tools.Shortcut;
22
23/**
24 * Distributes the selected nodes to equal distances along a line.
25 *
26 * @author Teemu Koskinen
27 */
28public final class DistributeAction extends JosmAction {
29
30 public DistributeAction() {
31 super(tr("Distribute Nodes"), "distribute", tr("Distribute the selected nodes to equal distances along a line."),
32 Shortcut.registerShortcut("tools:distribute", tr("Tool: {0}", tr("Distribute Nodes")), KeyEvent.VK_B, Shortcut.GROUP_EDIT), true);
33 }
34
35 /**
36 * The general algorithm here is to find the two selected nodes
37 * that are furthest apart, and then to distribute all other selected
38 * nodes along the straight line between these nodes.
39 */
40 public void actionPerformed(ActionEvent e) {
41 if (!isEnabled())
42 return;
43 Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected();
44 Collection<Node> nodes = new LinkedList<Node>();
45 Collection<Node> itnodes = new LinkedList<Node>();
46 for (OsmPrimitive osm : sel)
47 if (osm instanceof Node) {
48 nodes.add((Node)osm);
49 itnodes.add((Node)osm);
50 }
51 // special case if no single nodes are selected and exactly one way is:
52 // then use the way's nodes
53 if ((nodes.size() == 0) && (sel.size() == 1)) {
54 for (OsmPrimitive osm : sel)
55 if (osm instanceof Way) {
56 nodes.addAll(((Way)osm).getNodes());
57 itnodes.addAll(((Way)osm).getNodes());
58 }
59 }
60
61 if (nodes.size() < 3) {
62 OptionPaneUtil.showMessageDialog(
63 Main.parent,
64 tr("Please select at least three nodes."),
65 tr("Information"),
66 JOptionPane.INFORMATION_MESSAGE
67 );
68 return;
69 }
70
71 // Find from the selected nodes two that are the furthest apart.
72 // Let's call them A and B.
73 double distance = 0;
74
75 Node nodea = null;
76 Node nodeb = null;
77
78 for (Node n : nodes) {
79 itnodes.remove(n);
80 for (Node m : itnodes) {
81 double dist = Math.sqrt(n.getEastNorth().distance(m.getEastNorth()));
82 if (dist > distance) {
83 nodea = n;
84 nodeb = m;
85 distance = dist;
86 }
87 }
88 }
89
90 // Remove the nodes A and B from the list of nodes to move
91 nodes.remove(nodea);
92 nodes.remove(nodeb);
93
94 // Find out co-ords of A and B
95 double ax = nodea.getEastNorth().east();
96 double ay = nodea.getEastNorth().north();
97 double bx = nodeb.getEastNorth().east();
98 double by = nodeb.getEastNorth().north();
99
100 // A list of commands to do
101 Collection<Command> cmds = new LinkedList<Command>();
102
103 // Amount of nodes between A and B plus 1
104 int num = nodes.size()+1;
105
106 // Current number of node
107 int pos = 0;
108 while (nodes.size() > 0) {
109 pos++;
110 Node s = null;
111
112 // Find the node that is furthest from B (i.e. closest to A)
113 distance = 0.0;
114 for (Node n : nodes) {
115 double dist = Math.sqrt(nodeb.getEastNorth().distance(n.getEastNorth()));
116 if (dist > distance) {
117 s = n;
118 distance = dist;
119 }
120 }
121
122 // First move the node to A's position, then move it towards B
123 double dx = ax - s.getEastNorth().east() + (bx-ax)*pos/num;
124 double dy = ay - s.getEastNorth().north() + (by-ay)*pos/num;
125
126 cmds.add(new MoveCommand(s, dx, dy));
127
128 //remove moved node from the list
129 nodes.remove(s);
130 }
131
132 // Do it!
133 Main.main.undoRedo.add(new SequenceCommand(tr("Distribute Nodes"), cmds));
134 Main.map.repaint();
135 }
136
137 @Override
138 protected void updateEnabledState() {
139 setEnabled(getCurrentDataSet() != null && !getCurrentDataSet().getSelected().isEmpty());
140 }
141}
Note: See TracBrowser for help on using the repository browser.