Changeset 15574 in josm for trunk/test


Ignore:
Timestamp:
2019-12-09T09:47:20+01:00 (5 years ago)
Author:
GerdP
Message:

fix #18367 and #18385: CombineWayAction (C) refuses to combine ways or silently reverses ways
Changes:

  • try first to combine the ways with the method Multipolygon.joinWays() If that method returns a single line string we can use it, else use the result of NodeGraph.buildSpanningPathNoRemove(). Both methods will not add or remove segments
  • if ways are combined execute checks for overlapping segments or self-intersection and show a notification popup right after the command was added to the UndoRedoHandler
  • The code which handles reversed ways needed changes. In the unpatched version it sometimes claims wrongly that ways were reversed, in special cases it sometimes silently reverted ways. The old code did not handle the case properly that a node can appear more than once. I really hope that I got it right now.
  • Fix some sonarlint issues
  • let NodeGraph routines return an ArrayList instead of a LinkedList (improves performance a bit)
  • Add unit tests
Location:
trunk/test
Files:
4 added
1 edited

Legend:

Unmodified
Added
Removed
  • trunk/test/unit/org/openstreetmap/josm/actions/CombineWayActionTest.java

    r15558 r15574  
    33
    44import static org.junit.Assert.assertEquals;
    5 import static org.junit.Assert.assertNull;
    6 import static org.junit.Assert.assertTrue;
     5import static org.junit.Assert.assertFalse;
    76
    87import java.io.IOException;
    98import java.io.InputStream;
    109import java.util.ArrayList;
     10import java.util.Collection;
    1111import java.util.Collections;
    1212import java.util.HashSet;
     13import java.util.LinkedList;
    1314import java.util.List;
    1415import java.util.Set;
     
    1920import org.openstreetmap.josm.data.osm.DataSet;
    2021import org.openstreetmap.josm.data.osm.Node;
    21 import org.openstreetmap.josm.data.osm.NodeGraph;
    2222import org.openstreetmap.josm.data.osm.NodePair;
    2323import org.openstreetmap.josm.data.osm.Way;
     
    5050        try (InputStream is = TestUtils.getRegressionDataStream(11957, "data.osm")) {
    5151            DataSet ds = OsmReader.parseDataSet(is, null);
    52             NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(ds.getWays());
    53             List<Node> path = graph.buildSpanningPathNoRemove();
     52            List<Node> path = CombineWayAction.tryJoin(ds.getWays());
    5453            assertEquals(10, path.size());
    5554            Set<Long> firstAndLastObtained = new HashSet<>();
     
    7271        try (InputStream is = TestUtils.getRegressionDataStream(18385, "data.osm")) {
    7372            DataSet ds = OsmReader.parseDataSet(is, null);
    74             NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(ds.getWays());
    75             List<Node> path = graph.buildSpanningPathNoRemove();
    76             assertNull(path);
     73            List<Node> path = CombineWayAction.tryJoin(ds.getWays());
     74            assertFalse(path.isEmpty());
    7775        }
    7876    }
     
    9189            if (!selection.get(0).isNew())
    9290                Collections.reverse(selection);
    93             NodeGraph graph = NodeGraph.createNearlyUndirectedGraphFromNodeWays(selection);
    94             List<Node> path = graph.buildSpanningPathNoRemove();
    95             assertTrue(path != null);
     91            double expectedLen = getOriginalLength(selection);
     92            List<Node> path = CombineWayAction.tryJoin(selection);
     93            assertFalse(path.isEmpty());
     94            Way combined = new Way(0);
     95            combined.setNodes(path);
     96            assertEquals(expectedLen, combined.getLength(), 0.01);
    9697        }
    9798    }
     99
     100    /**
     101     * Non-regression test for bug #18367 (Lines cannot be combined when they share an overlapping segment)
     102     * @throws IOException if any I/O error occurs
     103     * @throws IllegalDataException if OSM parsing fails
     104     */
     105    @Test
     106    public void testTicket18367() throws IOException, IllegalDataException {
     107        try (InputStream is = TestUtils.getRegressionDataStream(18367, "nocombine.osm")) {
     108            DataSet ds = OsmReader.parseDataSet(is, null);
     109            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
     110            assertEquals(2, selection.size());
     111            double expectedLen = getOriginalLength(selection);
     112            List<Node> path = CombineWayAction.tryJoin(selection);
     113            assertFalse(path.isEmpty());
     114            Way combined = new Way(0);
     115            combined.setNodes(path);
     116            assertEquals(expectedLen, combined.getLength(), 1e-7);
     117        }
     118    }
     119
     120
     121    /**
     122     * Non-regression test for bug #18367
     123     * @throws IOException if any I/O error occurs
     124     * @throws IllegalDataException if OSM parsing fails
     125     */
     126    @Test
     127    public void testTicket18367NeedsSplit() throws IOException, IllegalDataException {
     128        try (InputStream is = TestUtils.getRegressionDataStream(18367, "split-and-reverse.osm")) {
     129            DataSet ds = OsmReader.parseDataSet(is, null);
     130            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
     131            assertEquals(2, selection.size());
     132            double expectedLen = getOriginalLength(selection);
     133            List<Node> path = CombineWayAction.tryJoin(selection);
     134            assertFalse(path.isEmpty());
     135            Way combined = new Way(0);
     136            combined.setNodes(path);
     137            assertEquals(expectedLen, combined.getLength(), 1e-7);
     138            List<Way> reversedWays = new LinkedList<>();
     139            List<Way> unreversedWays = new LinkedList<>();
     140            CombineWayAction.detectReversedWays(selection, path, reversedWays, unreversedWays);
     141            assertFalse(reversedWays.isEmpty());
     142        }
     143    }
     144
     145
     146    /**
     147     * Test for bad reverse way detection. See #18367
     148     * @throws IOException if any I/O error occurs
     149     * @throws IllegalDataException if OSM parsing fails
     150     */
     151    @Test
     152    public void testDetectReversedWays() throws IOException, IllegalDataException {
     153        try (InputStream is = TestUtils.getRegressionDataStream(18367, "silent-revert.osm")) {
     154            DataSet ds = OsmReader.parseDataSet(is, null);
     155            ArrayList<Way> selection = new ArrayList<>(ds.getWays());
     156            assertEquals(2, selection.size());
     157            // make sure that short way is first
     158            if (selection.get(0).getNodesCount() != 2)
     159                Collections.reverse(selection);
     160            double expectedLen = getOriginalLength(selection);
     161            List<Node> path = CombineWayAction.tryJoin(selection);
     162            assertFalse(path.isEmpty());
     163            Way combined = new Way(0);
     164            combined.setNodes(path);
     165            assertEquals(expectedLen, combined.getLength(), 1e-7);
     166            List<Way> reversedWays = new LinkedList<>();
     167            List<Way> unreversedWays = new LinkedList<>();
     168            CombineWayAction.detectReversedWays(selection, path, reversedWays, unreversedWays);
     169            assertFalse(reversedWays.contains(selection.get(0)));
     170        }
     171    }
     172
    98173
    99174    /**
     
    107182            .verify();
    108183    }
     184
     185    private static double getOriginalLength(Collection<Way> ways) {
     186        double len = 0;
     187        for (Way w : ways) {
     188            len += w.getLength();
     189        }
     190        return len;
     191    }
     192
    109193}
Note: See TracChangeset for help on using the changeset viewer.