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

Last change on this file since 2491 was 2323, checked in by Gubaer, 14 years ago

Added explicit help topics
See also current list of help topics with links to source files and to help pages

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