// License: GPL. For details, see LICENSE file.
package org.openstreetmap.josm.plugins.utilsplugin2.actions;
import static org.openstreetmap.josm.gui.help.HelpUtil.ht;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.awt.event.ActionEvent;
import java.awt.event.KeyEvent;
import java.util.Collection;
import java.util.HashSet;
import java.util.LinkedList;
import javax.swing.JOptionPane;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.actions.JosmAction;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.command.MoveCommand;
import org.openstreetmap.josm.command.SequenceCommand;
import org.openstreetmap.josm.data.coor.EastNorth;
import org.openstreetmap.josm.data.osm.Node;
import org.openstreetmap.josm.data.osm.OsmPrimitive;
import org.openstreetmap.josm.data.osm.Way;
import org.openstreetmap.josm.gui.Notification;
import org.openstreetmap.josm.tools.Shortcut;
/**
* Mirror the selected ways nodes or ways along line given by two first selected points
*
* Note: If a ways are selected, their nodes are mirrored
*
* @author Alexei Kasatkin, based on much copy&Paste from other MirrorAction :)
*/
public final class SymmetryAction extends JosmAction {
/**
* Constructs a new {@code SymmetryAction}.
*/
public SymmetryAction() {
super(tr("Symmetry"), "symmetry", tr("Mirror selected nodes and ways."),
Shortcut.registerShortcut("tools:symmetry", tr("Tool: {0}", tr("Symmetry")),
KeyEvent.VK_S, Shortcut.ALT_SHIFT), true);
putValue("help", ht("/Action/Symmetry"));
}
@Override
public void actionPerformed(ActionEvent e) {
Collection<OsmPrimitive> sel = getLayerManager().getEditDataSet().getSelected();
HashSet<Node> nodes = new HashSet<>();
EastNorth p1 = null, p2 = null;
for (OsmPrimitive osm : sel) {
if (osm instanceof Node) {
if (p1 == null) p1 = ((Node) osm).getEastNorth(); else
if (p2 == null) p2 = ((Node) osm).getEastNorth(); else
nodes.add((Node) osm);
}
}
for (OsmPrimitive osm : sel) {
if (osm instanceof Way) {
nodes.addAll(((Way) osm).getNodes());
}
}
if (p1 == null || p2 == null || nodes.size() < 1) {
new Notification(
tr("Please select at least two nodes for symmetry axis and something else to mirror.")
).setIcon(JOptionPane.WARNING_MESSAGE).show();
return;
}
double ne, nn, l, e0, n0;
e0 = p1.east();
n0 = p1.north();
ne = -(p2.north() - p1.north());
nn = (p2.east() - p1.east());
l = Math.hypot(ne, nn);
ne /= l; nn /= l; // normal unit vector
Collection<Command> cmds = new LinkedList<>();
for (Node n : nodes) {
EastNorth c = n.getEastNorth();
double pr = (c.east()-e0)*ne + (c.north()-n0)*nn;
//pr=10;
cmds.add(new MoveCommand(n, -2*ne*pr, -2*nn*pr));
}
Main.main.undoRedo.add(new SequenceCommand(tr("Symmetry"), cmds));
Main.map.repaint();
}
@Override
protected void updateEnabledState() {
updateEnabledStateOnCurrentSelection();
}
@Override
protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) {
setEnabled(selection != null && !selection.isEmpty());
}
}