Ignore:
Timestamp:
2010-12-07T09:53:12+01:00 (12 years ago)
Author:
bastiK
Message:

applied #5652 (patch by Olivier Croquette) - add support for scaling objects

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.
    12package org.openstreetmap.josm.command;
    23
     
    45
    56import java.util.Collection;
    6 import java.util.HashMap;
    7 import java.util.LinkedList;
    8 import java.util.Map;
    97
    108import javax.swing.JLabel;
    119
    1210import org.openstreetmap.josm.data.coor.EastNorth;
    13 import org.openstreetmap.josm.data.coor.LatLon;
    1411import org.openstreetmap.josm.data.osm.Node;
    1512import org.openstreetmap.josm.data.osm.OsmPrimitive;
    16 import org.openstreetmap.josm.data.osm.visitor.AllNodesVisitor;
    1713import org.openstreetmap.josm.tools.ImageProvider;
    1814
     
    2218 * @author Frederik Ramm <frederik@remote.org>
    2319 */
    24 public class RotateCommand extends Command {
     20public class RotateCommand extends TransformNodesCommand {
    2521
    2622    /**
    27      * The objects to rotate.
    28      */
    29     private Collection<Node> nodes = new LinkedList<Node>();
    30 
    31     /**
    32      * pivot point
     23     * Pivot point
    3324     */
    3425    private EastNorth pivot;
    3526
    3627    /**
    37      * Small helper for holding the interesting part of the old data state of the
    38      * objects.
     28     * World position of the mouse when the user started the command.
     29     *
    3930     */
    40     public static class OldState {
    41         LatLon latlon;
    42         EastNorth eastNorth;
    43         boolean modified;
    44     }
     31    EastNorth startEN = null;
    4532
    4633    /**
    4734     * angle of rotation starting click to pivot
    4835     */
    49     private double startAngle;
     36    private double startAngle = 0.0;
    5037
    5138    /**
    5239     * computed rotation angle between starting click and current mouse pos
    5340     */
    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;
    6042
    6143    /**
    6244     * 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.
    6646     */
    67     public RotateCommand(Collection<OsmPrimitive> objects, EastNorth start, EastNorth end) {
     47    public RotateCommand(Collection<OsmPrimitive> objects, EastNorth currentEN) {
     48        super(objects);
    6849
    69         this.nodes = AllNodesVisitor.getAllNodes(objects);
    70         pivot = new EastNorth(0,0);
     50        pivot = getNodesCenter();
    7151
    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;
    8157
    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());
    8471    }
    8572
    8673    /**
    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.
    9075     */
    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();
    9781    }
    9882
    9983    /**
    100      * Helper for actually rotationg the nodes.
    101      * @param setModified - true if rotated nodes should be flagged "modified"
     84     * Rotate nodes.
    10285     */
    103     private void rotateNodes(boolean setModified) {
     86    @Override
     87    protected void transformNodes() {
    10488        for (Node n : nodes) {
    10589            double cosPhi = Math.cos(rotationAngle);
    10690            double sinPhi = Math.sin(rotationAngle);
    107             EastNorth oldEastNorth = oldState.get(n).eastNorth;
     91            EastNorth oldEastNorth = oldStates.get(n).eastNorth;
    10892            double x = oldEastNorth.east() - pivot.east();
    10993            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();
    11296            n.setEastNorth(new EastNorth(nx, ny));
    113             if (setModified) {
    114                 n.setModified(true);
    115             }
    11697        }
    11798    }
    11899
    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() {
    139102        return new JLabel(trn("Rotate {0} node", "Rotate {0} nodes", nodes.size(), nodes.size()), ImageProvider.get("data", "node"), JLabel.HORIZONTAL);
    140103    }
    141 
    142     public Collection<Node> getRotatedNodes() {
    143         return nodes;
    144     }
    145104}
Note: See TracChangeset for help on using the changeset viewer.