//License: GPL. Copyright 2007 by Immanuel Scholz and others package org.openstreetmap.josm.actions; import static org.openstreetmap.josm.tools.I18n.tr; import static org.openstreetmap.josm.gui.help.HelpUtil.ht; import java.awt.event.ActionEvent; import java.awt.event.KeyEvent; import java.util.ArrayList; import java.util.Collection; import java.util.Collections; import java.util.HashMap; import java.util.HashSet; import java.util.LinkedList; import java.util.List; import java.util.Map; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.command.ChangeCommand; import org.openstreetmap.josm.command.Command; import org.openstreetmap.josm.command.SequenceCommand; 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.data.osm.WaySegment; import org.openstreetmap.josm.tools.Shortcut; public class JoinNodeWayAction extends JosmAction { public JoinNodeWayAction() { super(tr("Join Node to Way"), "joinnodeway", tr("Join a node into the nearest way segments"), Shortcut.registerShortcut("tools:joinnodeway", tr("Tool: {0}", tr("Join Node to Way")), KeyEvent.VK_J, Shortcut.GROUP_EDIT), true); putValue("help", ht("/Action/JoinNodeWay")); } public void actionPerformed(ActionEvent e) { if (!isEnabled()) return; Collection<OsmPrimitive> sel = getCurrentDataSet().getSelected(); if (sel.size() != 1 || !(sel.iterator().next() instanceof Node)) return; Node node = (Node) sel.iterator().next(); List<WaySegment> wss = Main.map.mapView.getNearestWaySegments( Main.map.mapView.getPoint(node), OsmPrimitive.isSelectablePredicate); HashMap<Way, List<Integer>> insertPoints = new HashMap<Way, List<Integer>>(); for (WaySegment ws : wss) { List<Integer> is; if (insertPoints.containsKey(ws.way)) { is = insertPoints.get(ws.way); } else { is = new ArrayList<Integer>(); insertPoints.put(ws.way, is); } if (ws.way.getNode(ws.lowerIndex) != node && ws.way.getNode(ws.lowerIndex+1) != node) { is.add(ws.lowerIndex); } } Collection<Command> cmds = new LinkedList<Command>(); for (Map.Entry<Way, List<Integer>> insertPoint : insertPoints.entrySet()) { List<Integer> is = insertPoint.getValue(); if (is.size() == 0) continue; Way w = insertPoint.getKey(); List<Node> nodesToAdd = w.getNodes(); pruneSuccsAndReverse(is); for (int i : is) { nodesToAdd.add(i+1, node); } Way wnew = new Way(w); wnew.setNodes(nodesToAdd); cmds.add(new ChangeCommand(w, wnew)); } if (cmds.size() == 0) return; Main.main.undoRedo.add(new SequenceCommand(tr("Join Node and Line"), cmds)); Main.map.repaint(); } private static void pruneSuccsAndReverse(List<Integer> is) { //if (is.size() < 2) return; HashSet<Integer> is2 = new HashSet<Integer>(); for (int i : is) { if (!is2.contains(i - 1) && !is2.contains(i + 1)) { is2.add(i); } } is.clear(); is.addAll(is2); Collections.sort(is); Collections.reverse(is); } @Override protected void updateEnabledState() { if (getCurrentDataSet() == null) { setEnabled(false); } else { updateEnabledState(getCurrentDataSet().getSelected()); } } @Override protected void updateEnabledState(Collection<? extends OsmPrimitive> selection) { setEnabled(selection != null && !selection.isEmpty()); } }