- Timestamp:
- 2010-12-07T09:53:12+01:00 (14 years ago)
- Location:
- trunk/src/org/openstreetmap/josm
- Files:
-
- 2 added
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/SelectAction.java
r3642 r3702 27 27 import org.openstreetmap.josm.command.MoveCommand; 28 28 import org.openstreetmap.josm.command.RotateCommand; 29 import org.openstreetmap.josm.command.ScaleCommand; 29 30 import org.openstreetmap.josm.command.SequenceCommand; 30 31 import org.openstreetmap.josm.data.coor.EastNorth; … … 61 62 //static private final Logger logger = Logger.getLogger(SelectAction.class.getName()); 62 63 63 enum Mode { move, rotate, select } 64 enum Mode { move, rotate, scale, select } 65 64 66 private Mode mode = null; 65 67 private SelectionManager selectionManager; 66 67 68 private boolean cancelDrawMode = false; 68 69 private boolean didMouseDrag = false; 69 70 70 /** 71 71 * The component this SelectAction is associated with. 72 72 */ 73 73 private final MapView mv; 74 75 74 /** 76 75 * The old cursor before the user pressed the mouse button. 77 76 */ 78 77 private Cursor oldCursor; 79 80 /** 81 * The position of the mouse before the user moves a node. 82 */ 83 private Point mousePos; 84 78 /** 79 * The position of the mouse before the user starts to drag it while pressing a button. 80 */ 81 private Point startingDraggingPos; 82 /** 83 * The last known position of the mouse. 84 */ 85 private Point lastMousePos; 85 86 /** 86 87 * The time of the user mouse down event. 87 88 */ 88 89 private long mouseDownTime = 0; 89 90 90 /** 91 91 * The time which needs to pass between click and release before something … … 93 93 */ 94 94 private int initialMoveDelay; 95 96 95 /** 97 96 * The screen distance which needs to be travelled before something … … 106 105 */ 107 106 public SelectAction(MapFrame mapFrame) { 108 super(tr("Select"), "move/move", tr("Select, move and rotate objects"),107 super(tr("Select"), "move/move", tr("Select, move, scale and rotate objects"), 109 108 Shortcut.registerShortcut("mapmode:select", tr("Mode: {0}", tr("Select")), KeyEvent.VK_S, Shortcut.GROUP_EDIT), 110 109 mapFrame, … … 113 112 putValue("help", "Action/Move/Move"); 114 113 selectionManager = new SelectionManager(this, false, mv); 115 initialMoveDelay = Main.pref.getInteger("edit.initial-move-delay", 200);116 initialMoveThreshold = Main.pref.getInteger("edit.initial-move-threshold", 5);114 initialMoveDelay = Main.pref.getInteger("edit.initial-move-delay", 200); 115 initialMoveThreshold = Main.pref.getInteger("edit.initial-move-threshold", 5); 117 116 } 118 117 … … 139 138 } 140 139 141 @Override public void enterMode() { 140 @Override 141 public void enterMode() { 142 142 super.enterMode(); 143 143 mv.addMouseListener(this); … … 147 147 } 148 148 149 @Override public void exitMode() { 149 @Override 150 public void exitMode() { 150 151 super.exitMode(); 151 152 selectionManager.unregister(mv); … … 160 161 * mouse (which will become selected). 161 162 */ 162 @Override public void mouseDragged(MouseEvent e) { 163 if(!mv.isActiveLayerVisible()) 163 @Override 164 public void mouseDragged(MouseEvent e) { 165 if (!mv.isActiveLayerVisible()) 164 166 return; 165 167 166 168 cancelDrawMode = true; 167 if (mode == Mode.select) return; 169 if (mode == Mode.select) 170 return; 168 171 169 172 // do not count anything as a move if it lasts less than 100 milliseconds. 170 if ((mode == Mode.move) && (System.currentTimeMillis() - mouseDownTime < initialMoveDelay)) return; 171 172 if(mode != Mode.rotate) // button is pressed in rotate mode 173 if ((mode == Mode.move) && (System.currentTimeMillis() - mouseDownTime < initialMoveDelay)) 174 return; 175 176 if (mode != Mode.rotate && mode != Mode.scale) // button is pressed in rotate mode 177 { 173 178 if ((e.getModifiersEx() & MouseEvent.BUTTON1_DOWN_MASK) == 0) 174 179 return; 180 } 175 181 176 182 if (mode == Mode.move) { … … 178 184 } 179 185 186 if (startingDraggingPos == null) { 187 startingDraggingPos = new Point(e.getX(), e.getY()); 188 } 189 180 190 if (!initialMoveThresholdExceeded) { 181 int dxp = mousePos.x - e.getX(); 182 int dyp = mousePos.y - e.getY(); 183 int dp = (int) Math.sqrt(dxp*dxp+dyp*dyp); 184 if (dp < initialMoveThreshold) return; 191 int dxp = lastMousePos.x - e.getX(); 192 int dyp = lastMousePos.y - e.getY(); 193 int dp = (int) Math.sqrt(dxp * dxp + dyp * dyp); 194 if (dp < initialMoveThreshold) 195 return; 185 196 initialMoveThresholdExceeded = true; 186 197 } 187 198 188 EastNorth mouseEN = mv.getEastNorth(e.getX(), e.getY()); 189 EastNorth mouseStartEN = mv.getEastNorth(mousePos.x, mousePos.y); 190 double dx = mouseEN.east() - mouseStartEN.east(); 191 double dy = mouseEN.north() - mouseStartEN.north(); 199 EastNorth currentEN = mv.getEastNorth(e.getX(), e.getY()); 200 EastNorth lastEN = mv.getEastNorth(lastMousePos.x, lastMousePos.y); 201 //EastNorth startEN = mv.getEastNorth(startingDraggingPos.x, startingDraggingPos.y); 202 double dx = currentEN.east() - lastEN.east(); 203 double dy = currentEN.north() - lastEN.north(); 192 204 if (dx == 0 && dy == 0) 193 205 return; … … 199 211 Way w = virtualWay.way; 200 212 Way wnew = new Way(w); 201 wnew.addNode(virtualWay.lowerIndex +1, virtualNode);213 wnew.addNode(virtualWay.lowerIndex + 1, virtualNode); 202 214 virtualCmds.add(new ChangeCommand(w, wnew)); 203 215 } … … 207 219 virtualWays.size()); 208 220 Main.main.undoRedo.add(new SequenceCommand(text, virtualCmds)); 209 getCurrentDataSet().setSelected(Collections.singleton((OsmPrimitive) virtualNode));221 getCurrentDataSet().setSelected(Collections.singleton((OsmPrimitive) virtualNode)); 210 222 virtualWays.clear(); 211 223 virtualNode = null; 212 224 } else { 213 // Currently we support moving and rotating,which do not affect relations.225 // Currently we support only transformations which do not affect relations. 214 226 // So don't add them in the first place to make handling easier 215 227 Collection<OsmPrimitive> selection = getCurrentDataSet().getSelectedNodesAndWays(); 216 228 Collection<Node> affectedNodes = AllNodesVisitor.getAllNodes(selection); 217 229 218 // when rotating, having only one node makes no sense - quit silently219 if ( mode == Mode.rotate && affectedNodes.size() < 2)230 // for these transformations, having only one node makes no sense - quit silently 231 if (affectedNodes.size() < 2 && (mode == Mode.rotate || mode == Mode.scale)) 220 232 return; 221 233 222 234 Command c = !Main.main.undoRedo.commands.isEmpty() 223 ? Main.main.undoRedo.commands.getLast() : null;235 ? Main.main.undoRedo.commands.getLast() : null; 224 236 if (c instanceof SequenceCommand) { 225 c = ((SequenceCommand) c).getLastCommand();237 c = ((SequenceCommand) c).getLastCommand(); 226 238 } 227 239 228 240 if (mode == Mode.move) { 229 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) {230 ((MoveCommand) c).moveAgain(dx,dy);241 if (c instanceof MoveCommand && affectedNodes.equals(((MoveCommand) c).getParticipatingPrimitives())) { 242 ((MoveCommand) c).moveAgain(dx, dy); 231 243 } else { 232 244 Main.main.undoRedo.add( … … 243 255 tr("Cannot move objects outside of the world."), 244 256 tr("Warning"), 245 JOptionPane.WARNING_MESSAGE 246 247 ); 257 JOptionPane.WARNING_MESSAGE); 248 258 restoreCursor(); 249 259 return; … … 251 261 } 252 262 } else if (mode == Mode.rotate) { 253 if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand) c).getRotatedNodes())) {254 ((RotateCommand) c).rotateAgain(mouseStartEN, mouseEN);263 if (c instanceof RotateCommand && affectedNodes.equals(((RotateCommand) c).getTransformedNodes())) { 264 ((RotateCommand) c).handleEvent(currentEN); 255 265 } else { 256 Main.main.undoRedo.add(new RotateCommand(selection, mouseStartEN, mouseEN)); 266 Main.main.undoRedo.add(new RotateCommand(selection, currentEN)); 267 } 268 } else if (mode == Mode.scale) { 269 if (c instanceof ScaleCommand && affectedNodes.equals(((ScaleCommand) c).getTransformedNodes())) { 270 ((ScaleCommand) c).handleEvent(currentEN); 271 } else { 272 Main.main.undoRedo.add(new ScaleCommand(selection, currentEN)); 257 273 } 258 274 } … … 260 276 261 277 mv.repaint(); 262 mousePos = e.getPoint(); 278 if (mode != Mode.scale) { 279 lastMousePos = e.getPoint(); 280 } 263 281 264 282 didMouseDrag = true; 265 283 } 266 284 267 @Override public void mouseMoved(MouseEvent e) { 285 @Override 286 public void mouseMoved(MouseEvent e) { 268 287 // Mac OSX simulates with ctrl + mouse 1 the second mouse button hence no dragging events get fired. 269 288 // 270 if ((Main.platform instanceof PlatformHookOsx) && mode == Mode.rotate) {289 if ((Main.platform instanceof PlatformHookOsx) && (mode == Mode.rotate || mode == Mode.scale)) { 271 290 mouseDragged(e); 272 291 } 273 292 } 274 275 293 private Node virtualNode = null; 276 294 private Collection<WaySegment> virtualWays = new LinkedList<WaySegment>(); … … 295 313 Way w = null; 296 314 297 for (WaySegment ws : mv.getNearestWaySegments(p, OsmPrimitive.isSelectablePredicate)) {315 for (WaySegment ws : mv.getNearestWaySegments(p, OsmPrimitive.isSelectablePredicate)) { 298 316 w = ws.way; 299 317 300 318 Point2D p1 = mv.getPoint2D(wnp.a = w.getNode(ws.lowerIndex)); 301 Point2D p2 = mv.getPoint2D(wnp.b = w.getNode(ws.lowerIndex+1)); 302 if(SimplePaintVisitor.isLargeSegment(p1, p2, virtualSpace)) 303 { 304 Point2D pc = new Point2D.Double((p1.getX()+p2.getX())/2, (p1.getY()+p2.getY())/2); 305 if (p.distanceSq(pc) < virtualSnapDistSq) 306 { 319 Point2D p2 = mv.getPoint2D(wnp.b = w.getNode(ws.lowerIndex + 1)); 320 if (SimplePaintVisitor.isLargeSegment(p1, p2, virtualSpace)) { 321 Point2D pc = new Point2D.Double((p1.getX() + p2.getX()) / 2, (p1.getY() + p2.getY()) / 2); 322 if (p.distanceSq(pc) < virtualSnapDistSq) { 307 323 // Check that only segments on top of each other get added to the 308 324 // virtual ways list. Otherwise ways that coincidentally have their … … 327 343 return !virtualWays.isEmpty(); 328 344 } 329 330 345 private Collection<OsmPrimitive> cycleList = Collections.emptyList(); 331 346 private boolean cyclePrims = false; … … 347 362 boolean waitForMouseUp = Main.pref.getBoolean("mappaint.select.waits-for-mouse-up", false); 348 363 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 349 boolean alt = ((e.getModifiers() & (ActionEvent.ALT_MASK|InputEvent.ALT_GRAPH_MASK)) != 0 350 || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false)); 364 boolean alt = ((e.getModifiers() & (ActionEvent.ALT_MASK | InputEvent.ALT_GRAPH_MASK)) != 0 || Main.pref.getBoolean("selectaction.cycles.multiple.matches", false)); 351 365 352 366 if (!alt) { … … 364 378 } 365 379 366 if (cycleList.size() >1) {380 if (cycleList.size() > 1) { 367 381 cyclePrims = false; 368 382 … … 378 392 // special case: for cycle groups of 2, we can toggle to the 379 393 // true nearest primitive on mousePressed right away 380 if (cycleList.size() ==2 && !waitForMouseUp) {394 if (cycleList.size() == 2 && !waitForMouseUp) { 381 395 if (!(osm.equals(old) || osm.isNew() || ctrl)) { 382 396 cyclePrims = false; … … 405 419 * cursor to movement. 406 420 */ 407 @Override public void mousePressed(MouseEvent e) { 421 @Override 422 public void mousePressed(MouseEvent e) { 408 423 debug("mousePressed: e.getPoint()=" + e.getPoint()); 409 424 410 425 // return early 411 if(!mv.isActiveLayerVisible() 412 || !(Boolean)this.getValue("active") 413 || e.getButton() != MouseEvent.BUTTON1) 426 if (!mv.isActiveLayerVisible() || !(Boolean) this.getValue("active") || e.getButton() != MouseEvent.BUTTON1) { 414 427 return; 428 } 415 429 416 430 // request focus in order to enable the expected keyboard shortcuts … … 419 433 boolean ctrl = (e.getModifiers() & ActionEvent.CTRL_MASK) != 0; 420 434 boolean shift = (e.getModifiers() & ActionEvent.SHIFT_MASK) != 0; 435 boolean alt = (e.getModifiers() & ActionEvent.ALT_MASK) != 0; 421 436 422 437 // We don't want to change to draw tool if the user tries to (de)select … … 426 441 initialMoveThresholdExceeded = false; 427 442 mouseDownTime = System.currentTimeMillis(); 428 mousePos = e.getPoint();443 lastMousePos = e.getPoint(); 429 444 430 445 Collection<OsmPrimitive> c = MapView.asColl( … … 443 458 setCursor(ImageProvider.getCursor("rotate", null)); 444 459 mv.repaint(); 460 } else if (alt && ctrl) { 461 mode = Mode.scale; 462 463 if (getCurrentDataSet().getSelected().isEmpty()) { 464 getCurrentDataSet().setSelected(c); 465 } 466 467 // Mode.select redraws when selectPrims is called 468 // Mode.move redraws when mouseDragged is called 469 // Mode.scale redraws here 470 setCursor(ImageProvider.getCursor("scale", null)); 471 mv.repaint(); 445 472 } else if (!c.isEmpty()) { 446 473 mode = Mode.move; … … 466 493 debug("mouseReleased: e.getPoint()=" + e.getPoint()); 467 494 468 if (!mv.isActiveLayerVisible())495 if (!mv.isActiveLayerVisible()) { 469 496 return; 497 } 498 499 startingDraggingPos = null; 470 500 471 501 restoreCursor(); … … 474 504 475 505 // Select Draw Tool if no selection has been made 476 if (getCurrentDataSet().getSelected().size() == 0 && !cancelDrawMode) {506 if (getCurrentDataSet().getSelected().size() == 0 && !cancelDrawMode) { 477 507 Main.map.selectDrawTool(true); 478 508 return; … … 488 518 // do nothing if the click was to short to be recognized as a drag, 489 519 // but the release position is farther than 10px away from the press position 490 if ( mousePos.distanceSq(e.getPoint())<100) {520 if (lastMousePos.distanceSq(e.getPoint()) < 100) { 491 521 selectPrims(cyclePrims(cycleList, e), e, true, false); 492 522 493 523 // If the user double-clicked a node, change to draw mode 494 524 Collection<OsmPrimitive> c = getCurrentDataSet().getSelected(); 495 if (e.getClickCount() >=2 && c.size() == 1 && c.iterator().next() instanceof Node) {525 if (e.getClickCount() >= 2 && c.size() == 1 && c.iterator().next() instanceof Node) { 496 526 // We need to do it like this as otherwise drawAction will see a double 497 527 // click and switch back to SelectMode 498 Main.worker.execute(new Runnable(){ 528 Main.worker.execute(new Runnable() { 529 499 530 public void run() { 500 531 Main.map.selectDrawTool(true); … … 508 539 for (OsmPrimitive osm : getCurrentDataSet().getSelected()) { 509 540 if (osm instanceof Way) { 510 limit -= ((Way) osm).getNodes().size();541 limit -= ((Way) osm).getNodes().size(); 511 542 } 512 543 if ((limit -= 1) < 0) { … … 518 549 Main.parent, 519 550 tr("Move elements"), 520 new String[] {tr("Move them"), tr("Undo move")}); 521 ed.setButtonIcons(new String[] {"reorder.png", "cancel.png"}); 522 ed.setContent(tr("You moved more than {0} elements. " 523 + "Moving a large number of elements is often an error.\n" 524 + "Really move them?", max)); 551 new String[]{tr("Move them"), tr("Undo move")}); 552 ed.setButtonIcons(new String[]{"reorder.png", "cancel.png"}); 553 ed.setContent(tr("You moved more than {0} elements. " + "Moving a large number of elements is often an error.\n" + "Really move them?", max)); 525 554 ed.setCancelButton(2); 526 555 ed.toggleEnable("movedManyElements"); 527 556 ed.showDialog(); 528 557 529 if (ed.getValue() != 1) {558 if (ed.getValue() != 1) { 530 559 Main.main.undoRedo.undo(); 531 560 } … … 572 601 nxt = first; 573 602 574 for (Iterator<OsmPrimitive> i = prims.iterator(); i.hasNext(); 603 for (Iterator<OsmPrimitive> i = prims.iterator(); i.hasNext();) { 575 604 if (cyclePrims && shift) { 576 605 if (!(nxt = i.next()).isSelected()) { … … 631 660 632 661 Command cmd = MergeNodesAction.mergeNodes(Main.main.getEditLayer(), nodesToMerge, target.iterator().next()); 633 if (cmd != null) {662 if (cmd != null) { 634 663 Main.main.undoRedo.add(cmd); 635 664 } … … 644 673 645 674 // not allowed together: do not change dataset selection, return early 646 if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty())) 675 if ((shift && ctrl) || (ctrl && !released) || (!virtualWays.isEmpty())) { 647 676 return; 677 } 648 678 649 679 if (!released) { … … 672 702 } 673 703 674 @Override public String getModeHelpText() { 675 if (mode == Mode.select) 704 @Override 705 public String getModeHelpText() { 706 if (mode == Mode.select) { 676 707 return tr("Release the mouse button to select the objects in the rectangle."); 677 else if (mode == Mode.move)708 } else if (mode == Mode.move) { 678 709 return tr("Release the mouse button to stop moving. Ctrl to merge with nearest node."); 679 else if (mode == Mode.rotate)710 } else if (mode == Mode.rotate) { 680 711 return tr("Release the mouse button to stop rotating."); 681 else 682 return tr("Move objects by dragging; Shift to add to selection (Ctrl to toggle); Shift-Ctrl to rotate selected; or change selection"); 683 } 684 685 @Override public boolean layerIsSupported(Layer l) { 712 } else if (mode == Mode.scale) { 713 return tr("Release the mouse button to stop scaling."); 714 } else { 715 return tr("Move objects by dragging; Shift to add to selection (Ctrl to toggle); Shift-Ctrl to rotate selected; Alt-Ctrl to scale selected; or change selection"); 716 } 717 } 718 719 @Override 720 public boolean layerIsSupported(Layer l) { 686 721 return l instanceof OsmDataLayer; 687 722 } -
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.