Ticket #18189: 18189.patch

File 18189.patch, 5.8 KB (added by GerdP, 7 years ago)

Possible solution and first unit test

  • src/org/openstreetmap/josm/actions/JoinNodeWayAction.java

     
    1818import java.util.SortedSet;
    1919import java.util.TreeSet;
    2020
     21import javax.swing.JOptionPane;
     22
    2123import org.openstreetmap.josm.command.ChangeCommand;
    2224import org.openstreetmap.josm.command.Command;
    2325import org.openstreetmap.josm.command.MoveCommand;
     
    3234import org.openstreetmap.josm.data.projection.ProjectionRegistry;
    3335import org.openstreetmap.josm.gui.MainApplication;
    3436import org.openstreetmap.josm.gui.MapView;
     37import org.openstreetmap.josm.gui.Notification;
    3538import org.openstreetmap.josm.tools.Geometry;
    3639import org.openstreetmap.josm.tools.MultiMap;
    3740import org.openstreetmap.josm.tools.Shortcut;
     
    125128        }
    126129
    127130        // Execute phase: traverse the structure "data" and finally put the nodes into place
     131        Map<Node,EastNorth> moved = new HashMap<>();
    128132        for (Map.Entry<Way, MultiMap<Integer, Node>> entry : data.entrySet()) {
    129133            final Way w = entry.getKey();
    130134            final MultiMap<Integer, Node> innerEntry = entry.getValue();
     
    142146                                w.getNode(segmentIndex).getEastNorth(),
    143147                                w.getNode(segmentIndex+1).getEastNorth(),
    144148                                node.getEastNorth());
    145                         MoveCommand c = new MoveCommand(
    146                                 node, ProjectionRegistry.getProjection().eastNorth2latlon(newPosition));
    147                         // Avoid moving a given node several times at the same position in case of overlapping ways
    148                         if (!cmds.contains(c)) {
    149                             cmds.add(c);
     149                        EastNorth prevMove = moved.get(node);
     150                        if (prevMove != null) {
     151                            if (!prevMove.equalsEpsilon(newPosition, 1e-7)) {
     152                                new Notification(tr("Multiple target ways, no common point found. Nothing was changed."))
     153                                        .setIcon(JOptionPane.INFORMATION_MESSAGE)
     154                                        .show();
     155                                return;
     156                            }
     157                            continue;
    150158                        }
     159                        MoveCommand c = new MoveCommand(node,
     160                                ProjectionRegistry.getProjection().eastNorth2latlon(newPosition));
     161                        cmds.add(c);
     162                        moved.put(node, newPosition);
    151163                    }
    152164                }
    153165                List<Node> nodesToAdd = new LinkedList<>();
  • test/unit/org/openstreetmap/josm/actions/JoinNodeWayActionTest.java

     
     1// License: GPL. For details, see LICENSE file.
     2package org.openstreetmap.josm.actions;
     3
     4import static org.junit.Assert.assertTrue;
     5
     6import java.util.Arrays;
     7
     8import org.junit.Rule;
     9import org.junit.Test;
     10import org.openstreetmap.josm.data.coor.EastNorth;
     11import org.openstreetmap.josm.data.osm.DataSet;
     12import org.openstreetmap.josm.data.osm.Node;
     13import org.openstreetmap.josm.data.osm.Way;
     14import org.openstreetmap.josm.gui.MainApplication;
     15import org.openstreetmap.josm.gui.layer.OsmDataLayer;
     16import org.openstreetmap.josm.testutils.JOSMTestRules;
     17import org.openstreetmap.josm.tools.Geometry;
     18
     19import edu.umd.cs.findbugs.annotations.SuppressFBWarnings;
     20
     21/**
     22 * Unit tests for class {@link JoinNodeWayAction}.
     23 */
     24public final class JoinNodeWayActionTest {
     25
     26    /**
     27     * Setup test.
     28     */
     29    @Rule
     30    @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD")
     31    public JOSMTestRules test = new JOSMTestRules().projection().main().preferences();
     32
     33    /**
     34     * Test case: Move node onto two overlapping ways
     35     * see #18189 moveontoway.osm
     36     */
     37    @Test
     38    public void testTicket18189() {
     39        DataSet dataSet = new DataSet();
     40        OsmDataLayer layer = new OsmDataLayer(dataSet, OsmDataLayer.createNewName(), null);
     41        MainApplication.getLayerManager().addLayer(layer);
     42        Node n1 = new Node(new EastNorth(1, 1));
     43        Node n2 = new Node(new EastNorth(5, 5));
     44        Node n3 = new Node(new EastNorth(1, 1.000000001)); // very small difference
     45        Node n4 = new Node(new EastNorth(5, 5));
     46        Node n5 = new Node(new EastNorth(3, 3.1)); // node to move
     47
     48        dataSet.addPrimitive(n1);
     49        dataSet.addPrimitive(n2);
     50        dataSet.addPrimitive(n3);
     51        dataSet.addPrimitive(n4);
     52        dataSet.addPrimitive(n5);
     53
     54        Way w1 = new Way();
     55        w1.setNodes(Arrays.asList(n1, n2));
     56        dataSet.addPrimitive(w1);
     57        Way w2 = new Way();
     58        w2.setNodes(Arrays.asList(n3, n4));
     59        dataSet.addPrimitive(w2);
     60
     61        dataSet.addSelected(n5);
     62        EastNorth expected = Geometry.closestPointToSegment(n1.getEastNorth(), n2.getEastNorth(), n5.getEastNorth());
     63
     64        JoinNodeWayAction action = JoinNodeWayAction.createMoveNodeOntoWayAction();
     65        action.setEnabled(true);
     66        action.actionPerformed(null);
     67        // Make sure the node was only moved once
     68        assertTrue("Node n5 wasn't added to way w1.", w1.containsNode(n5));
     69        assertTrue("Node n5 wasn't added to way w2.", w2.containsNode(n5));
     70        assertTrue("Node was moved too unexpected position", n5.getEastNorth().equalsEpsilon(expected, 1e-7));
     71    }
     72}