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

Last change on this file since 2171 was 2017, checked in by Gubaer, 15 years ago

removed OptionPaneUtil
cleanup of deprecated Layer API
cleanup of deprecated APIs in OsmPrimitive and Way
cleanup of imports

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