source: josm/trunk/src/org/openstreetmap/josm/command/RotateCommand.java@ 2054

Last change on this file since 2054 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

  • Property svn:eol-style set to native
File size: 4.6 KB
Line 
1package org.openstreetmap.josm.command;
2
3import static org.openstreetmap.josm.tools.I18n.trn;
4
5import java.util.Collection;
6import java.util.HashMap;
7import java.util.LinkedList;
8import java.util.Map;
9
10import javax.swing.JLabel;
11import javax.swing.tree.DefaultMutableTreeNode;
12import javax.swing.tree.MutableTreeNode;
13
14import org.openstreetmap.josm.data.coor.EastNorth;
15import org.openstreetmap.josm.data.coor.LatLon;
16import org.openstreetmap.josm.data.osm.Node;
17import org.openstreetmap.josm.data.osm.OsmPrimitive;
18import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
19import org.openstreetmap.josm.tools.ImageProvider;
20
21/**
22 * RotateCommand rotates a number of objects around their centre.
23 *
24 * @author Frederik Ramm <frederik@remote.org>
25 */
26public class RotateCommand extends Command {
27
28 /**
29 * The objects to rotate.
30 */
31 private Collection<Node> nodes = new LinkedList<Node>();
32
33 /**
34 * pivot point
35 */
36 private EastNorth pivot;
37
38 /**
39 * Small helper for holding the interesting part of the old data state of the
40 * objects.
41 */
42 public static class OldState {
43 LatLon latlon;
44 EastNorth eastNorth;
45 boolean modified;
46 }
47
48 /**
49 * angle of rotation starting click to pivot
50 */
51 private double startAngle;
52
53 /**
54 * computed rotation angle between starting click and current mouse pos
55 */
56 private double rotationAngle;
57
58 /**
59 * List of all old states of the objects.
60 */
61 private Map<Node, OldState> oldState = new HashMap<Node, OldState>();
62
63 /**
64 * Creates a RotateCommand.
65 * Assign the initial object set, compute pivot point and rotation angle.
66 * Computation of pivot point is done by the same rules that are used in
67 * the "align nodes in circle" action.
68 */
69 public RotateCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
70
71 this.nodes = AllNodesVisitor.getAllNodes(objects);
72 pivot = new EastNorth(0,0);
73
74 for (Node n : this.nodes) {
75 OldState os = new OldState();
76 os.latlon = new LatLon(n.getCoor());
77 os.eastNorth = n.getEastNorth();
78 os.modified = n.modified;
79 oldState.put(n, os);
80 pivot = pivot.add(os.eastNorth.east(), os.eastNorth.north());
81 }
82 pivot = new EastNorth(pivot.east()/this.nodes.size(), pivot.north()/this.nodes.size());
83
84 rotationAngle = Math.PI/2;
85 rotateAgain(start, end);
86 }
87
88 /**
89 * Rotate the same set of objects again, by the angle between given
90 * start and end nodes. Internally this is added to the existing
91 * rotation so a later undo will undo the whole rotation.
92 */
93 public void rotateAgain(EastNorth start, EastNorth end) {
94 // compute angle
95 startAngle = Math.atan2(start.east()-pivot.east(), start.north()-pivot.north());
96 double endAngle = Math.atan2(end.east()-pivot.east(), end.north()-pivot.north());
97 rotationAngle += startAngle - endAngle;
98 rotateNodes(false);
99 }
100
101 /**
102 * Helper for actually rotationg the nodes.
103 * @param setModified - true if rotated nodes should be flagged "modified"
104 */
105 private void rotateNodes(boolean setModified) {
106 for (Node n : nodes) {
107 double cosPhi = Math.cos(rotationAngle);
108 double sinPhi = Math.sin(rotationAngle);
109 EastNorth oldEastNorth = oldState.get(n).eastNorth;
110 double x = oldEastNorth.east() - pivot.east();
111 double y = oldEastNorth.north() - pivot.north();
112 double nx = sinPhi * x + cosPhi * y + pivot.east();
113 double ny = -cosPhi * x + sinPhi * y + pivot.north();
114 n.setEastNorth(new EastNorth(nx, ny));
115 if (setModified) {
116 n.modified = true;
117 }
118 }
119 }
120
121 @Override public boolean executeCommand() {
122 rotateNodes(true);
123 return true;
124 }
125
126 @Override public void undoCommand() {
127 for (Node n : nodes) {
128 OldState os = oldState.get(n);
129 n.setCoor(os.latlon);
130 n.modified = os.modified;
131 }
132 }
133
134 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) {
135 for (OsmPrimitive osm : nodes) {
136 modified.add(osm);
137 }
138 }
139
140 @Override public MutableTreeNode description() {
141 return new DefaultMutableTreeNode(new JLabel(trn("Rotate {0} node", "Rotate {0} nodes", nodes.size(), nodes.size()), ImageProvider.get("data", "node"), JLabel.HORIZONTAL));
142 }
143
144 public Collection<Node> getRotatedNodes() {
145 return nodes;
146 }
147}
Note: See TracBrowser for help on using the repository browser.