Ticket #21856: 21856.patch
| File 21856.patch, 12.2 KB (added by , 4 years ago) |
|---|
-
src/org/openstreetmap/josm/command/SplitWayCommand.java
IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 diff --git a/src/org/openstreetmap/josm/command/SplitWayCommand.java b/src/org/openstreetmap/josm/command/SplitWayCommand.java
a b 487 487 if (isOrderedRelation) { 488 488 if (way.lastNode() == way.firstNode()) { 489 489 // Self-closing way. 490 direction = Direction.IRRELEVANT;490 direction = direction.merge(Direction.IRRELEVANT); 491 491 } else { 492 492 // For ordered relations, looking beyond the nearest neighbour members is not required, 493 493 // and can even cause the wrong direction to be guessed (with closed loops). … … 497 497 missingWays.add(w); 498 498 else { 499 499 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 500 direction = Direction.FORWARDS;500 direction = direction.merge(Direction.FORWARDS); 501 501 } else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) { 502 direction = Direction.BACKWARDS;502 direction = direction.merge(Direction.BACKWARDS); 503 503 } 504 504 } 505 505 } … … 509 509 missingWays.add(w); 510 510 else { 511 511 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 512 direction = Direction.BACKWARDS;512 direction = direction.merge(Direction.BACKWARDS); 513 513 } else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) { 514 direction = Direction.FORWARDS;514 direction = direction.merge(Direction.FORWARDS); 515 515 } 516 516 } 517 517 } … … 528 528 if (ir - k >= 0 && r.getMember(ir - k).isWay()) { 529 529 Way w = r.getMember(ir - k).getWay(); 530 530 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 531 direction = Direction.FORWARDS;531 direction = direction.merge(Direction.FORWARDS); 532 532 } else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) { 533 direction = Direction.BACKWARDS;533 direction = direction.merge(Direction.BACKWARDS); 534 534 } 535 535 break; 536 536 } 537 537 if (ir + k < r.getMembersCount() && r.getMember(ir + k).isWay()) { 538 538 Way w = r.getMember(ir + k).getWay(); 539 539 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 540 direction = Direction.BACKWARDS;540 direction = direction.merge(Direction.BACKWARDS); 541 541 } else if (w.firstNode() == way.lastNode() || w.lastNode() == way.lastNode()) { 542 direction = Direction.FORWARDS;542 direction = direction.merge(Direction.FORWARDS); 543 543 } 544 544 break; 545 545 } … … 951 951 FORWARDS, 952 952 BACKWARDS, 953 953 UNKNOWN, 954 IRRELEVANT 954 IRRELEVANT; 955 956 /** 957 * Merge directions (this helps avoid overriding {@link #FORWARDS} with {@link #BACKWARDS}). 958 * @param other The other direction to merge. {@link #UNKNOWN} will be overridden. 959 * @return The merged direction 960 */ 961 Direction merge(Direction other) { 962 if (this == other) { 963 return this; 964 } 965 if (this == IRRELEVANT || other == IRRELEVANT || 966 (this == FORWARDS && other == BACKWARDS) || 967 (other == FORWARDS && this == BACKWARDS)) { 968 return IRRELEVANT; 969 } 970 if (this == UNKNOWN) { 971 return other; 972 } 973 if (other == UNKNOWN) { 974 return this; 975 } 976 return UNKNOWN; 977 } 955 978 } 956 979 957 980 enum WarningType { -
src/org/openstreetmap/josm/data/osm/DataSet.java
IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 diff --git a/src/org/openstreetmap/josm/data/osm/DataSet.java b/src/org/openstreetmap/josm/data/osm/DataSet.java
a b 530 530 * @since 17981 531 531 */ 532 532 public void addPrimitiveRecursive(OsmPrimitive primitive) { 533 Stream<OsmPrimitive> children; 533 534 if (primitive instanceof Way) { 534 ((Way) primitive).getNodes().forEach(n -> addPrimitiveRecursive(n));535 children = ((Way) primitive).getNodes().stream().map(OsmPrimitive.class::cast); 535 536 } else if (primitive instanceof Relation) { 536 ((Relation) primitive).getMembers().forEach(m -> addPrimitiveRecursive(m.getMember())); 537 children = ((Relation) primitive).getMembers().stream().map(RelationMember::getMember); 538 } else { 539 children = Stream.empty(); 537 540 } 541 // Relations may have the same member multiple times. 542 children.filter(p -> !Objects.equals(this, p.getDataSet())).forEach(this::addPrimitiveRecursive); 538 543 addPrimitive(primitive); 539 544 } 540 545 -
test/unit/org/openstreetmap/josm/command/SplitWayCommandTest.java
IDEA additional info: Subsystem: com.intellij.openapi.diff.impl.patch.CharsetEP <+>UTF-8 diff --git a/test/unit/org/openstreetmap/josm/command/SplitWayCommandTest.java b/test/unit/org/openstreetmap/josm/command/SplitWayCommandTest.java
a b 1 1 // License: GPL. For details, see LICENSE file. 2 2 package org.openstreetmap.josm.command; 3 3 4 import static org.junit.jupiter.api.Assertions.assertAll; 4 5 import static org.junit.jupiter.api.Assertions.assertEquals; 5 6 import static org.junit.jupiter.api.Assertions.assertFalse; 6 7 import static org.junit.jupiter.api.Assertions.assertTrue; … … 11 12 import java.util.Arrays; 12 13 import java.util.Collections; 13 14 import java.util.Iterator; 15 import java.util.List; 14 16 import java.util.Optional; 15 17 16 18 import org.junit.jupiter.api.Test; 17 19 import org.junit.jupiter.api.extension.RegisterExtension; 20 import org.junit.jupiter.params.ParameterizedTest; 21 import org.junit.jupiter.params.provider.ValueSource; 18 22 import org.openstreetmap.josm.TestUtils; 19 23 import org.openstreetmap.josm.command.SplitWayCommand.Strategy; 20 24 import org.openstreetmap.josm.data.UndoRedoHandler; … … 26 30 import org.openstreetmap.josm.data.osm.Relation; 27 31 import org.openstreetmap.josm.data.osm.RelationMember; 28 32 import org.openstreetmap.josm.data.osm.Way; 33 import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType; 34 import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionTypeCalculator; 29 35 import org.openstreetmap.josm.io.IllegalDataException; 30 36 import org.openstreetmap.josm.io.OsmReader; 31 37 import org.openstreetmap.josm.testutils.JOSMTestRules; 32 38 33 39 import edu.umd.cs.findbugs.annotations.SuppressFBWarnings; 40 import org.openstreetmap.josm.testutils.annotations.BasicPreferences; 34 41 35 42 /** 36 43 * Unit tests for class {@link SplitWayCommand}. … … 42 49 */ 43 50 @RegisterExtension 44 51 @SuppressFBWarnings(value = "URF_UNREAD_PUBLIC_OR_PROTECTED_FIELD") 45 public JOSMTestRules test = new JOSMTestRules().main().projection().preferences();52 static JOSMTestRules test = new JOSMTestRules().main().projection().preferences(); 46 53 47 54 /** 48 55 * Unit test of {@link SplitWayCommand#findVias}. … … 433 440 } 434 441 } 435 442 443 /** 444 * Test case: smart ordering in routes 445 * See #21856 446 */ 447 @ParameterizedTest 448 @ValueSource(booleans = {false, true}) 449 void testTicket21856(boolean reverse) { 450 Way way1 = TestUtils.newWay("highway=residential", TestUtils.newNode(""), TestUtils.newNode("")); 451 way1.setOsmId(23_968_090, 1); 452 way1.lastNode().setOsmId(6_823_898_683L, 1); 453 Way way2 = TestUtils.newWay("highway=residential", way1.lastNode(), TestUtils.newNode("")); 454 way2.setOsmId(728_199_307, 1); 455 way2.lastNode().setOsmId(6_823_898_684L, 1); 456 Node splitNode = TestUtils.newNode(""); 457 splitNode.setOsmId(6_823_906_290L, 1); 458 Way splitWay = TestUtils.newWay("highway=service", way2.firstNode(), splitNode, TestUtils.newNode(""), way2.lastNode()); 459 // The behavior should be the same regardless of the direction of the way 460 if (reverse) { 461 List<Node> nodes = new ArrayList<>(splitWay.getNodes()); 462 Collections.reverse(nodes); 463 splitWay.setNodes(nodes); 464 } 465 splitWay.setOsmId(728_199_306, 1); 466 Relation route = TestUtils.newRelation("type=route route=bus", new RelationMember("", way1), new RelationMember("", splitWay), 467 new RelationMember("", way2), new RelationMember("", way1)); 468 DataSet dataSet = new DataSet(); 469 dataSet.addPrimitiveRecursive(route); 470 dataSet.setSelected(splitNode); 471 // Sanity check (preconditions -- the route should be well-formed already) 472 WayConnectionTypeCalculator connectionTypeCalculator = new WayConnectionTypeCalculator(); 473 List<WayConnectionType> links = connectionTypeCalculator.updateLinks(route, route.getMembers()); 474 assertAll("All links should be connected (forward)", links.subList(0, links.size() - 2).stream().map(link -> () -> assertTrue(link.linkNext))); 475 assertAll("All links should be connected (backward)", links.subList(1, links.size() - 1).stream().map(link -> () -> assertTrue(link.linkPrev))); 476 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay( 477 splitWay, 478 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)), 479 new ArrayList<>(), 480 Strategy.keepLongestChunk(), 481 // This split requires additional downloads but problem occured before the download 482 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY 483 ); 484 assertTrue(result.isPresent()); 485 result.get().executeCommand(); 486 // Actual check 487 connectionTypeCalculator = new WayConnectionTypeCalculator(); 488 links = connectionTypeCalculator.updateLinks(route, route.getMembers()); 489 assertAll("All links should be connected (forward)", links.subList(0, links.size() - 2).stream().map(link -> () -> assertTrue(link.linkNext))); 490 assertAll("All links should be connected (backward)", links.subList(1, links.size() - 1).stream().map(link -> () -> assertTrue(link.linkPrev))); 491 } 436 492 }
