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

Last change on this file since 1380 was 1380, checked in by stoecker, 15 years ago

fix #2145. Patch by Teemu Koskinen

File size: 4.3 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 Collection<OsmPrimitive> sel = Main.ds.getSelected();
41 Collection<Node> nodes = new LinkedList<Node>();
42 Collection<Node> itnodes = new LinkedList<Node>();
43 for (OsmPrimitive osm : sel)
44 if (osm instanceof Node) {
45 nodes.add((Node)osm);
46 itnodes.add((Node)osm);
47 }
48 // special case if no single nodes are selected and exactly one way is:
49 // then use the way's nodes
50 if ((nodes.size() == 0) && (sel.size() == 1))
51 for (OsmPrimitive osm : sel)
52 if (osm instanceof Way) {
53 nodes.addAll(((Way)osm).nodes);
54 itnodes.addAll(((Way)osm).nodes);
55 }
56
57 if (nodes.size() < 3) {
58 JOptionPane.showMessageDialog(Main.parent, tr("Please select at least three nodes."));
59 return;
60 }
61
62 // Find from the selected nodes two that are the furthest apart.
63 // Let's call them A and B.
64 double distance = 0;
65
66 Node nodea = null;
67 Node nodeb = null;
68
69 for (Node n : nodes) {
70 itnodes.remove(n);
71 for (Node m : itnodes) {
72 double dist = Math.sqrt(n.eastNorth.distance(m.eastNorth));
73 if (dist > distance) {
74 nodea = n;
75 nodeb = m;
76 distance = dist;
77 }
78 }
79 }
80
81 // Remove the nodes A and B from the list of nodes to move
82 nodes.remove(nodea);
83 nodes.remove(nodeb);
84
85 // Find out co-ords of A and B
86 double ax = nodea.eastNorth.east();
87 double ay = nodea.eastNorth.north();
88 double bx = nodeb.eastNorth.east();
89 double by = nodeb.eastNorth.north();
90
91 // A list of commands to do
92 Collection<Command> cmds = new LinkedList<Command>();
93
94 // Amount of nodes between A and B plus 1
95 int num = nodes.size()+1;
96
97 // Current number of node
98 int pos = 0;
99 while (nodes.size() > 0) {
100 pos++;
101 Node s = null;
102
103 // Find the node that is furthest from B (i.e. closest to A)
104 distance = 0.0;
105 for (Node n : nodes) {
106 double dist = Math.sqrt(nodeb.eastNorth.distance(n.eastNorth));
107 if (dist > distance) {
108 s = n;
109 distance = dist;
110 }
111 }
112
113 // First move the node to A's position, then move it towards B
114 double dx = ax - s.eastNorth.east() + (bx-ax)*pos/num;
115 double dy = ay - s.eastNorth.north() + (by-ay)*pos/num;
116
117 cmds.add(new MoveCommand(s, dx, dy));
118
119 //remove moved node from the list
120 nodes.remove(s);
121 }
122
123 // Do it!
124 Main.main.undoRedo.add(new SequenceCommand(tr("Distribute Nodes"), cmds));
125 Main.map.repaint();
126 }
127}
Note: See TracBrowser for help on using the repository browser.