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

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

removed dependencies to Main.ds, removed Main.ds
removed AddVisitor, NameVisitor, DeleteVisitor - unnecessary double dispatching for these simple cases

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