Changeset 3702 in josm for trunk/src/org/openstreetmap/josm/command
- Timestamp:
- 2010-12-07T09:53:12+01:00 (12 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/command
- Files:
-
- 2 added
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/command/RotateCommand.java
r3262 r3702 1 // License: GPL. For details, see LICENSE file. 1 2 package org.openstreetmap.josm.command; 2 3 … … 4 5 5 6 import java.util.Collection; 6 import java.util.HashMap;7 import java.util.LinkedList;8 import java.util.Map;9 7 10 8 import javax.swing.JLabel; 11 9 12 10 import org.openstreetmap.josm.data.coor.EastNorth; 13 import org.openstreetmap.josm.data.coor.LatLon;14 11 import org.openstreetmap.josm.data.osm.Node; 15 12 import org.openstreetmap.josm.data.osm.OsmPrimitive; 16 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;17 13 import org.openstreetmap.josm.tools.ImageProvider; 18 14 … … 22 18 * @author Frederik Ramm <frederik@remote.org> 23 19 */ 24 public class RotateCommand extends Command {20 public class RotateCommand extends TransformNodesCommand { 25 21 26 22 /** 27 * The objects to rotate. 28 */ 29 private Collection<Node> nodes = new LinkedList<Node>(); 30 31 /** 32 * pivot point 23 * Pivot point 33 24 */ 34 25 private EastNorth pivot; 35 26 36 27 /** 37 * Small helper for holding the interesting part of the old data state of the38 * objects.28 * World position of the mouse when the user started the command. 29 * 39 30 */ 40 public static class OldState { 41 LatLon latlon; 42 EastNorth eastNorth; 43 boolean modified; 44 } 31 EastNorth startEN = null; 45 32 46 33 /** 47 34 * angle of rotation starting click to pivot 48 35 */ 49 private double startAngle ;36 private double startAngle = 0.0; 50 37 51 38 /** 52 39 * computed rotation angle between starting click and current mouse pos 53 40 */ 54 private double rotationAngle; 55 56 /** 57 * List of all old states of the objects. 58 */ 59 private Map<Node, OldState> oldState = new HashMap<Node, OldState>(); 41 private double rotationAngle = 0.0; 60 42 61 43 /** 62 44 * Creates a RotateCommand. 63 * Assign the initial object set, compute pivot point and rotation angle. 64 * Computation of pivot point is done by the same rules that are used in 65 * the "align nodes in circle" action. 45 * Assign the initial object set, compute pivot point and inital rotation angle. 66 46 */ 67 public RotateCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) { 47 public RotateCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) { 48 super(objects); 68 49 69 this.nodes = AllNodesVisitor.getAllNodes(objects); 70 pivot = new EastNorth(0,0); 50 pivot = getNodesCenter(); 71 51 72 for (Node n : this.nodes) { 73 OldState os = new OldState(); 74 os.latlon = new LatLon(n.getCoor()); 75 os.eastNorth = n.getEastNorth(); 76 os.modified = n.isModified(); 77 oldState.put(n, os); 78 pivot = pivot.add(os.eastNorth.east(), os.eastNorth.north()); 79 } 80 pivot = new EastNorth(pivot.east()/this.nodes.size(), pivot.north()/this.nodes.size()); 52 // We remember the very first position of the mouse for this action. 53 // Note that SelectAction will keep the same ScaleCommand when the user 54 // releases the button and presses it again with the same modifiers. 55 // The very first point of this operation is stored here. 56 startEN = currentEN; 81 57 82 rotationAngle = Math.PI/2; 83 rotateAgain(start, end); 58 startAngle = getAngle(currentEN); 59 rotationAngle = 0.0; 60 61 handleEvent(currentEN); 62 } 63 64 /** 65 * Get angle between the horizontal axis and the line formed by the pivot and give points. 66 **/ 67 protected double getAngle(EastNorth currentEN) { 68 if ( pivot == null ) 69 return 0.0; // should never happen by contract 70 return Math.atan2(currentEN.east()-pivot.east(), currentEN.north()-pivot.north()); 84 71 } 85 72 86 73 /** 87 * Rotate the same set of objects again, by the angle between given 88 * start and end nodes. Internally this is added to the existing 89 * rotation so a later undo will undo the whole rotation. 74 * Compute new rotation angle and transform nodes accordingly. 90 75 */ 91 public void rotateAgain(EastNorth start, EastNorth end) { 92 // compute angle 93 startAngle = Math.atan2(start.east()-pivot.east(), start.north()-pivot.north()); 94 double endAngle = Math.atan2(end.east()-pivot.east(), end.north()-pivot.north()); 95 rotationAngle += startAngle - endAngle; 96 rotateNodes(false); 76 @Override 77 public void handleEvent(EastNorth currentEN) { 78 double currentAngle = getAngle(currentEN); 79 rotationAngle = currentAngle - startAngle; 80 transformNodes(); 97 81 } 98 82 99 83 /** 100 * Helper for actually rotationg the nodes. 101 * @param setModified - true if rotated nodes should be flagged "modified" 84 * Rotate nodes. 102 85 */ 103 private void rotateNodes(boolean setModified) { 86 @Override 87 protected void transformNodes() { 104 88 for (Node n : nodes) { 105 89 double cosPhi = Math.cos(rotationAngle); 106 90 double sinPhi = Math.sin(rotationAngle); 107 EastNorth oldEastNorth = oldState .get(n).eastNorth;91 EastNorth oldEastNorth = oldStates.get(n).eastNorth; 108 92 double x = oldEastNorth.east() - pivot.east(); 109 93 double y = oldEastNorth.north() - pivot.north(); 110 double nx = sinPhi * x + cosPhi * y + pivot.east();111 double ny = - cosPhi * x + sinPhi * y + pivot.north();94 double nx = cosPhi * x + sinPhi * y + pivot.east(); 95 double ny = -sinPhi * x + cosPhi * y + pivot.north(); 112 96 n.setEastNorth(new EastNorth(nx, ny)); 113 if (setModified) {114 n.setModified(true);115 }116 97 } 117 98 } 118 99 119 @Override public boolean executeCommand() { 120 rotateNodes(true); 121 return true; 122 } 123 124 @Override public void undoCommand() { 125 for (Node n : nodes) { 126 OldState os = oldState.get(n); 127 n.setCoor(os.latlon); 128 n.setModified(os.modified); 129 } 130 } 131 132 @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { 133 for (OsmPrimitive osm : nodes) { 134 modified.add(osm); 135 } 136 } 137 138 @Override public JLabel getDescription() { 100 @Override 101 public JLabel getDescription() { 139 102 return new JLabel(trn("Rotate {0} node", "Rotate {0} nodes", nodes.size(), nodes.size()), ImageProvider.get("data", "node"), JLabel.HORIZONTAL); 140 103 } 141 142 public Collection<Node> getRotatedNodes() {143 return nodes;144 }145 104 }
Note: See TracChangeset
for help on using the changeset viewer.