source: josm/trunk/test/unit/org/openstreetmap/josm/command/SplitWayCommandTest.java

Last change on this file was 19198, checked in by stoecker, 11 months ago

fix checkstyle

File size: 27.2 KB
Line 
1// License: GPL. For details, see LICENSE file.
2package org.openstreetmap.josm.command;
3
4import static org.junit.jupiter.api.Assertions.assertAll;
5import static org.junit.jupiter.api.Assertions.assertEquals;
6import static org.junit.jupiter.api.Assertions.assertFalse;
7import static org.junit.jupiter.api.Assertions.assertTrue;
8
9import java.io.IOException;
10import java.io.InputStream;
11import java.util.ArrayList;
12import java.util.Arrays;
13import java.util.Collections;
14import java.util.Iterator;
15import java.util.List;
16import java.util.Optional;
17import java.util.stream.Stream;
18
19import org.junit.jupiter.api.Test;
20import org.junit.jupiter.params.ParameterizedTest;
21import org.junit.jupiter.params.provider.Arguments;
22import org.junit.jupiter.params.provider.MethodSource;
23import org.junit.jupiter.params.provider.ValueSource;
24import org.openstreetmap.josm.TestUtils;
25import org.openstreetmap.josm.command.SplitWayCommand.Strategy;
26import org.openstreetmap.josm.data.UndoRedoHandler;
27import org.openstreetmap.josm.data.coor.LatLon;
28import org.openstreetmap.josm.data.osm.DataSet;
29import org.openstreetmap.josm.data.osm.Node;
30import org.openstreetmap.josm.data.osm.OsmPrimitive;
31import org.openstreetmap.josm.data.osm.OsmPrimitiveType;
32import org.openstreetmap.josm.data.osm.Relation;
33import org.openstreetmap.josm.data.osm.RelationMember;
34import org.openstreetmap.josm.data.osm.Way;
35import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionType;
36import org.openstreetmap.josm.gui.dialogs.relation.sort.WayConnectionTypeCalculator;
37import org.openstreetmap.josm.io.IllegalDataException;
38import org.openstreetmap.josm.io.OsmReader;
39import org.openstreetmap.josm.testutils.annotations.BasicPreferences;
40import org.openstreetmap.josm.testutils.annotations.Main;
41import org.openstreetmap.josm.testutils.annotations.Projection;
42
43/**
44 * Unit tests for class {@link SplitWayCommand}.
45 */
46@BasicPreferences
47@Main
48@Projection
49final class SplitWayCommandTest {
50 /**
51 * Unit test of {@link SplitWayCommand#findVias}.
52 */
53 @Test
54 void testFindVias() {
55 // empty relation
56 assertTrue(SplitWayCommand.findVias(new Relation(), null).isEmpty());
57 // restriction relation without via member
58 Relation r = new Relation();
59 r.addMember(new RelationMember("", new Node()));
60 assertTrue(SplitWayCommand.findVias(r, "restriction").isEmpty());
61 // restriction relation with via member
62 r = new Relation();
63 OsmPrimitive via = new Node();
64 r.addMember(new RelationMember("via", via));
65 assertEquals(Collections.singletonList(via), SplitWayCommand.findVias(r, "restriction"));
66 // destination_sign relation without sign nor intersection
67 r = new Relation();
68 r.addMember(new RelationMember("", new Node()));
69 assertTrue(SplitWayCommand.findVias(r, "destination_sign").isEmpty());
70 // destination_sign with sign
71 r = new Relation();
72 via = new Node();
73 r.addMember(new RelationMember("sign", via));
74 assertEquals(Collections.singletonList(via), SplitWayCommand.findVias(r, "destination_sign"));
75 // destination_sign with intersection
76 r = new Relation();
77 via = new Node();
78 r.addMember(new RelationMember("intersection", via));
79 assertEquals(Collections.singletonList(via), SplitWayCommand.findVias(r, "destination_sign"));
80 }
81
82 static Stream<Arguments> testRouteRelation() {
83 Stream.Builder<Arguments> builder = Stream.builder();
84 for (int i = 0; i < 4; i++) {
85 builder.add(Arguments.of(false, i));
86 builder.add(Arguments.of(true, i));
87 }
88 return builder.build();
89 }
90
91 /**
92 * Unit tests of route relations.
93 */
94 @ParameterizedTest
95 @MethodSource
96 void testRouteRelation(final boolean wayIsReversed, final int indexOfWayToKeep) {
97 final DataSet dataSet = new DataSet();
98 final Node n1 = new Node(new LatLon(1, 0));
99 final Node n2 = new Node(new LatLon(2, 0));
100 final Node n3 = new Node(new LatLon(3, 0));
101 final Node n4 = new Node(new LatLon(4, 0));
102 final Node n5 = new Node(new LatLon(5, 0));
103 final Node n6 = new Node(new LatLon(6, 0));
104 final Node n7 = new Node(new LatLon(7, 0));
105 final Way w1 = new Way();
106 final Way w2 = new Way();
107 final Way w3 = new Way();
108 final Relation route = new Relation();
109 for (OsmPrimitive p : Arrays.asList(n1, n2, n3, n4, n5, n6, n7, w1, w2, w3, route)) {
110 dataSet.addPrimitive(p);
111 }
112 w1.setNodes(Arrays.asList(n1, n2));
113 w2.setNodes(wayIsReversed
114 ? Arrays.asList(n6, n5, n4, n3, n2)
115 : Arrays.asList(n2, n3, n4, n5, n6)
116 );
117 w3.setNodes(Arrays.asList(n6, n7));
118 route.put("type", "route");
119 route.addMember(new RelationMember("", w1));
120 route.addMember(new RelationMember("", w2));
121 route.addMember(new RelationMember("", w3));
122 dataSet.setSelected(Arrays.asList(w2, n3, n4, n5));
123
124 final Strategy strategy = wayChunks -> {
125 final Iterator<Way> it = wayChunks.iterator();
126 for (int i = 0; i < indexOfWayToKeep; i++) {
127 it.next();
128 }
129 return it.next();
130 };
131 final SplitWayCommand result = SplitWayCommand.splitWay(
132 w2, SplitWayCommand.buildSplitChunks(w2, Arrays.asList(n3, n4, n5)), new ArrayList<>(), strategy);
133 UndoRedoHandler.getInstance().add(result);
134
135 assertEquals(6, route.getMembersCount());
136 assertEquals(w1, route.getMemberPrimitivesList().get(0));
137 assertEquals(w3, route.getMemberPrimitivesList().get(5));
138 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(0)), n1);
139 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(0)), n2);
140 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(1)), n2);
141 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(1)), n3);
142 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(2)), n3);
143 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(2)), n4);
144 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(3)), n4);
145 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(3)), n5);
146 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(4)), n5);
147 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(4)), n6);
148 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(5)), n6);
149 assertFirstLastNodeIs(((Way) route.getMemberPrimitivesList().get(5)), n7);
150 }
151
152 @Test
153 void testOneMemberOrderedRelationShowsWarningTest() {
154 final DataSet dataSet = new DataSet();
155
156 // Positive IDs to mark that these ways are incomplete (i.e., no nodes loaded).
157 final Way w1 = new Way(1);
158 final Way w3 = new Way(3);
159
160 // The way we are going to split is complete of course.
161 final Node n1 = new Node(new LatLon(1, 0));
162 final Node n2 = new Node(new LatLon(2, 0));
163 final Node n3 = new Node(new LatLon(3, 0));
164 final Way w2 = new Way();
165
166 final Relation route = new Relation();
167 for (OsmPrimitive p : Arrays.asList(n1, n2, n3, w1, w2, w3, route)) {
168 dataSet.addPrimitive(p);
169 }
170 w2.setNodes(Arrays.asList(n1, n2, n3));
171
172 route.put("type", "route");
173 route.addMember(new RelationMember("", w1));
174 route.addMember(new RelationMember("", w2));
175 route.addMember(new RelationMember("", w3));
176 dataSet.setSelected(Arrays.asList(w2, n2));
177
178 // This split cannot be safely performed without downloading extra relation members.
179 // Here we ask the split method to abort if it needs more information.
180 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
181 w2,
182 SplitWayCommand.buildSplitChunks(w2, Collections.singletonList(n2)),
183 new ArrayList<>(),
184 Strategy.keepLongestChunk(),
185 SplitWayCommand.WhenRelationOrderUncertain.ABORT
186 );
187
188 assertFalse(result.isPresent());
189 }
190
191 static Stream<Arguments> testIncompleteMembersOrderedRelationCorrectOrderTest() {
192 Stream.Builder<Arguments> builder = Stream.builder();
193 for (int i = 0; i < 2; i++) {
194 // All these permutations should result in a split that keeps the new parts in order.
195 builder.add(Arguments.of(false, false, i));
196 builder.add(Arguments.of(true, false, i));
197 builder.add(Arguments.of(true, true, i));
198 builder.add(Arguments.of(false, true, i));
199 }
200 return builder.build();
201 }
202
203 @ParameterizedTest
204 @MethodSource
205 void testIncompleteMembersOrderedRelationCorrectOrderTest(final boolean reverseWayOne,
206 final boolean reverseWayTwo,
207 final int indexOfWayToKeep) {
208 final DataSet dataSet = new DataSet();
209
210 // Positive IDs to mark that these ways are incomplete (i.e., no nodes loaded).
211 final Way w1 = new Way(1);
212 final Way w4 = new Way(3);
213
214 // The ways we are going to split are complete of course.
215 final Node n1 = new Node(new LatLon(1, 0));
216 final Node n2 = new Node(new LatLon(2, 0));
217 final Node n3 = new Node(new LatLon(3, 0));
218 final Node n4 = new Node(new LatLon(4, 0));
219 final Node n5 = new Node(new LatLon(5, 0));
220 final Way w2 = new Way();
221 final Way w3 = new Way();
222
223 final Relation route = new Relation();
224 for (OsmPrimitive p : Arrays.asList(n1, n2, n3, n4, n5, w1, w2, w3, w4, route)) {
225 dataSet.addPrimitive(p);
226 }
227 w2.setNodes(reverseWayOne ? Arrays.asList(n3, n2, n1) : Arrays.asList(n1, n2, n3));
228 w3.setNodes(reverseWayTwo ? Arrays.asList(n5, n4, n3) : Arrays.asList(n3, n4, n5));
229
230 route.put("type", "route");
231 route.addMember(new RelationMember("", w1));
232 route.addMember(new RelationMember("", w2));
233 route.addMember(new RelationMember("", w3));
234 route.addMember(new RelationMember("", w4));
235
236 Way splitWay = indexOfWayToKeep == 0 ? w2 : w3;
237 Node splitNode = indexOfWayToKeep == 0 ? n2 : n4;
238
239 dataSet.setSelected(Arrays.asList(splitWay, splitNode));
240
241 final SplitWayCommand result = SplitWayCommand.splitWay(
242 splitWay, SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)), new ArrayList<>());
243 UndoRedoHandler.getInstance().add(result);
244
245 assertEquals(5, route.getMembersCount());
246 assertConnectedAtEnds(route.getMember(1).getWay(), route.getMember(2).getWay());
247 assertConnectedAtEnds(route.getMember(2).getWay(), route.getMember(3).getWay());
248 }
249
250 static void assertFirstLastNodeIs(Way way, Node node) {
251 assertTrue(node.equals(way.firstNode()) || node.equals(way.lastNode()),
252 "First/last node of " + way + " should be " + node);
253 }
254
255 static void assertConnectedAtEnds(Way one, Way two) {
256 Node first1 = one.firstNode();
257 Node last1 = one.lastNode();
258 Node first2 = two.firstNode();
259 Node last2 = two.lastNode();
260
261 assertTrue(first1 == first2 || first1 == last2 || last1 == first2 || last1 == last2,
262 "Ways expected to be connected at their ends.");
263 }
264
265 /**
266 * Non-regression test for patch #18596 (Fix relation ordering after split-way)
267 * @throws IOException if any I/O error occurs
268 * @throws IllegalDataException if OSM parsing fails
269 */
270 @Test
271 void testTicket18596() throws IOException, IllegalDataException {
272 try (InputStream is = TestUtils.getRegressionDataStream(18596, "data.osm")) {
273 DataSet ds = OsmReader.parseDataSet(is, null);
274
275 Way splitWay = (Way) ds.getPrimitiveById(5, OsmPrimitiveType.WAY);
276 Node splitNode = (Node) ds.getPrimitiveById(100002, OsmPrimitiveType.NODE);
277
278 final SplitWayCommand result = SplitWayCommand.splitWay(
279 splitWay,
280 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
281 new ArrayList<>()
282 );
283
284 UndoRedoHandler.getInstance().add(result);
285
286 Relation relation = (Relation) ds.getPrimitiveById(8888, OsmPrimitiveType.RELATION);
287
288 assertEquals(8, relation.getMembersCount());
289
290 // Before the patch introduced in #18596, these asserts would fail. The two parts of
291 // way '5' would be in the wrong order, breaking the boundary relation in this test.
292 assertConnectedAtEnds(relation.getMember(4).getWay(), relation.getMember(5).getWay());
293 assertConnectedAtEnds(relation.getMember(5).getWay(), relation.getMember(6).getWay());
294 }
295 }
296
297 /**
298 * Non-regression test for issue #17400 (Warn when splitting way in not fully downloaded region)
299 * <p>
300 * Bus route 190 gets broken when the split occurs, because the two new way parts are inserted in the relation in
301 * the wrong order.
302 *
303 * @throws IOException if any I/O error occurs
304 * @throws IllegalDataException if OSM parsing fails
305 */
306 @Test
307 void testTicket17400() throws IOException, IllegalDataException {
308 try (InputStream is = TestUtils.getRegressionDataStream(17400, "data.osm")) {
309 DataSet ds = OsmReader.parseDataSet(is, null);
310
311 Way splitWay = (Way) ds.getPrimitiveById(253731928, OsmPrimitiveType.WAY);
312 Node splitNode = (Node) ds.getPrimitiveById(29830834, OsmPrimitiveType.NODE);
313
314 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
315 splitWay,
316 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
317 new ArrayList<>(),
318 Strategy.keepLongestChunk(),
319 // This split requires no additional downloads.
320 SplitWayCommand.WhenRelationOrderUncertain.ABORT
321 );
322
323 assertTrue(result.isPresent());
324
325 UndoRedoHandler.getInstance().add(result.get());
326
327 // 190 Hormersdorf-Thalheim-Stollberg.
328 Relation relation = (Relation) ds.getPrimitiveById(2873422, OsmPrimitiveType.RELATION);
329
330 // One more than the original 161.
331 assertEquals(162, relation.getMembersCount());
332
333 // Before the patch introduced in #18596, these asserts would fail. The new parts of
334 // the Hauptstraße would be in the wrong order, breaking the bus route relation.
335 // These parts should be connected, in their relation sequence: 74---75---76.
336 // Before #18596 this would have been a broken connection: 74---75-x-76.
337 assertConnectedAtEnds(relation.getMember(74).getWay(), relation.getMember(75).getWay());
338 assertConnectedAtEnds(relation.getMember(75).getWay(), relation.getMember(76).getWay());
339 }
340 }
341
342 /**
343 * Non-regression test for issue #18863 (Asking for download of missing members when not needed)
344 * <p>
345 * A split on node 4518025255 caused the 'download missing members?' dialog to pop up for relation 68745 (CB 2),
346 * even though the way members next to the split way were already downloaded. This happened because this relation
347 * does not have its members connected at all.
348 * <p>
349 * This split should not trigger any download action at all.
350 *
351 * @throws IOException if any I/O error occurs
352 * @throws IllegalDataException if OSM parsing fails
353 */
354 @Test
355 void testTicket18863() throws IOException, IllegalDataException {
356 try (InputStream is = TestUtils.getRegressionDataStream(18863, "data.osm.bz2")) {
357 DataSet ds = OsmReader.parseDataSet(is, null);
358
359 Way splitWay = (Way) ds.getPrimitiveById(290581177L, OsmPrimitiveType.WAY);
360 Node splitNode = (Node) ds.getPrimitiveById(4518025255L, OsmPrimitiveType.NODE);
361
362 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
363 splitWay,
364 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
365 new ArrayList<>(),
366 Strategy.keepLongestChunk(),
367 // This split requires no additional downloads. If any are needed, this command will fail.
368 SplitWayCommand.WhenRelationOrderUncertain.ABORT
369 );
370
371 // Should not result in aborting the split.
372 assertTrue(result.isPresent());
373 }
374 }
375
376 /**
377 * Non-regression test for issue #19432 (AIOOB: Problem with member check with duplicate members)
378 *
379 * @throws IOException if any I/O error occurs
380 * @throws IllegalDataException if OSM parsing fails
381 */
382 @Test
383 void testTicket19432() throws IOException, IllegalDataException {
384 try (InputStream is = TestUtils.getRegressionDataStream(19432, "josm_split_way_exception_example.osm.bz2")) {
385 DataSet ds = OsmReader.parseDataSet(is, null);
386
387 Way splitWay = (Way) ds.getPrimitiveById(632576744L, OsmPrimitiveType.WAY);
388 Node splitNode = (Node) ds.getPrimitiveById(1523436358L, OsmPrimitiveType.NODE);
389
390 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
391 splitWay,
392 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
393 new ArrayList<>(),
394 Strategy.keepLongestChunk(),
395 // This split requires additional downloads but problem occured before the download
396 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY
397 );
398
399 // Should not result in aborting the split.
400 assertTrue(result.isPresent());
401 }
402 }
403
404 /**
405 * Non-regression test for issue #20163 (Split way corrupts relation when splitting via way)
406 *
407 * @throws IOException if any I/O error occurs
408 * @throws IllegalDataException if OSM parsing fails
409 */
410 @Test
411 void testTicket20163() throws IOException, IllegalDataException {
412 try (InputStream is = TestUtils.getRegressionDataStream(20163, "data-20163.osm")) {
413 DataSet ds = OsmReader.parseDataSet(is, null);
414
415 Way splitWay = (Way) ds.getPrimitiveById(757606841L, OsmPrimitiveType.WAY);
416 Node splitNode = splitWay.getNode(1);
417 Relation r = (Relation) ds.getPrimitiveById(10452821L, OsmPrimitiveType.RELATION);
418 assertEquals(3, r.getMembersCount());
419 assertFalse(r.getMembersFor(Collections.singleton(splitWay)).isEmpty());
420 assertEquals(1, r.getMembers().stream().filter(rm -> "via".equals(rm.getRole())).count());
421 assertEquals("via", r.getMembersFor(Collections.singleton(splitWay)).iterator().next().getRole());
422 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
423 splitWay,
424 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
425 new ArrayList<>(),
426 Strategy.keepLongestChunk(),
427 // This split requires additional downloads but problem occured before the download
428 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY
429 );
430
431 // Should not result in aborting the split.
432 assertTrue(result.isPresent());
433 result.get().executeCommand();
434
435 assertTrue(r.isModified());
436 assertEquals(4, r.getMembersCount());
437 assertEquals(2, r.getMembers().stream().filter(rm -> "via".equals(rm.getRole())).count());
438 }
439 }
440
441 /**
442 * Test case: smart ordering in routes
443 * See #21856
444 */
445 @ParameterizedTest
446 @ValueSource(booleans = {false, true})
447 void testTicket21856(boolean reverse) {
448 Way way1 = TestUtils.newWay("highway=residential", TestUtils.newNode(""), TestUtils.newNode(""));
449 way1.setOsmId(23_968_090, 1);
450 way1.lastNode().setOsmId(6_823_898_683L, 1);
451 Way way2 = TestUtils.newWay("highway=residential", way1.lastNode(), TestUtils.newNode(""));
452 way2.setOsmId(728_199_307, 1);
453 way2.lastNode().setOsmId(6_823_898_684L, 1);
454 Node splitNode = TestUtils.newNode("");
455 splitNode.setOsmId(6_823_906_290L, 1);
456 Way splitWay = TestUtils.newWay("highway=service", way2.firstNode(), splitNode, TestUtils.newNode(""), way2.lastNode());
457 // The behavior should be the same regardless of the direction of the way
458 if (reverse) {
459 List<Node> nodes = new ArrayList<>(splitWay.getNodes());
460 Collections.reverse(nodes);
461 splitWay.setNodes(nodes);
462 }
463 splitWay.setOsmId(728_199_306, 1);
464 Relation route = TestUtils.newRelation("type=route route=bus", new RelationMember("", way1), new RelationMember("", splitWay),
465 new RelationMember("", way2), new RelationMember("", way1));
466 DataSet dataSet = new DataSet();
467 dataSet.addPrimitiveRecursive(route);
468 dataSet.setSelected(splitNode);
469 // Sanity check (preconditions -- the route should be well-formed already)
470 assertWellFormedRoute(route);
471 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
472 splitWay,
473 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)),
474 new ArrayList<>(),
475 Strategy.keepLongestChunk(),
476 // This split requires additional downloads but problem occurred before the download
477 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY
478 );
479 assertTrue(result.isPresent());
480 result.get().executeCommand();
481 // Actual check
482 assertWellFormedRoute(route);
483 }
484
485 @Test
486 void testTicket21856DoublePoints() {
487 final Way incomplete = new Way(1082474948, 10);
488 final Way way1 = TestUtils.newWay("highway=residential", new Node(new LatLon(47.9971473, 8.1274441)),
489 new Node(new LatLon(48.0011535, 8.1363531)));
490 final Way way2 = TestUtils.newWay("highway=residential", new Node(new LatLon(48.0012294, 8.136414)),
491 new Node(new LatLon(48.0042513, 8.1378392)));
492 final Way splitWay = TestUtils.newWay("highway=residential", new Node(new LatLon(48.0011817, 8.1363763)),
493 new Node(new LatLon(48.0012086, 8.1363974)));
494 final Relation ptRelation = TestUtils.newRelation("type=route route=bus public_transport:version=2",
495 new RelationMember("", incomplete), new RelationMember("", way1),
496 new RelationMember("", splitWay), new RelationMember("", splitWay),
497 new RelationMember("", way1), new RelationMember("", incomplete));
498 final List<Node> splitLocations = splitWay.getNodes();
499 final DataSet ds = new DataSet();
500 way1.setOsmId(289122842, 10);
501 way2.setOsmId(30239125, 18);
502 splitWay.setOsmId(1082474946, 1);
503 ds.addPrimitiveRecursive(way1);
504 ds.addPrimitiveRecursive(way2);
505 ds.addPrimitiveRecursive(splitWay);
506 ds.addPrimitiveRecursive(incomplete);
507 ds.addPrimitive(ptRelation);
508 splitWay.addNode(0, way1.lastNode());
509 splitWay.addNode(way2.firstNode());
510
511 ds.setSelected(splitLocations);
512 assertWellFormedRoute(ptRelation);
513 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
514 splitWay,
515 SplitWayCommand.buildSplitChunks(splitWay, splitLocations),
516 new ArrayList<>(),
517 Strategy.keepLongestChunk(),
518 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY
519 );
520 assertTrue(result.isPresent());
521 result.get().executeCommand();
522 // Actual check
523 assertWellFormedRoute(ptRelation);
524 }
525
526 @Test
527 void testTicket21856DoublePointsRouteMiddle() {
528 final Way incomplete = new Way(1082474948, 10);
529 final Way way1 = TestUtils.newWay("highway=residential", new Node(new LatLon(47.9971473, 8.1274441)),
530 new Node(new LatLon(48.0011535, 8.1363531)));
531 final Way way2 = TestUtils.newWay("highway=residential", new Node(new LatLon(48.0012294, 8.136414)),
532 new Node(new LatLon(48.0042513, 8.1378392)));
533 final Way splitWay = TestUtils.newWay("highway=residential", new Node(new LatLon(48.0011817, 8.1363763)),
534 new Node(new LatLon(48.0012086, 8.1363974)));
535 final Relation ptRelation = TestUtils.newRelation("type=route route=bus public_transport:version=2",
536 new RelationMember("", incomplete), new RelationMember("", way1),
537 new RelationMember("", splitWay), new RelationMember("", way2),
538 new RelationMember("", way2), new RelationMember("", splitWay),
539 new RelationMember("", way1), new RelationMember("", incomplete));
540 final List<Node> splitLocations = splitWay.getNodes();
541 final DataSet ds = new DataSet();
542 way1.setOsmId(289122842, 10);
543 way2.setOsmId(30239125, 18);
544 splitWay.setOsmId(1082474946, 1);
545 ds.addPrimitiveRecursive(way1);
546 ds.addPrimitiveRecursive(way2);
547 ds.addPrimitiveRecursive(splitWay);
548 ds.addPrimitiveRecursive(incomplete);
549 ds.addPrimitive(ptRelation);
550 splitWay.addNode(0, way1.lastNode());
551 splitWay.addNode(way2.firstNode());
552
553 ds.setSelected(splitLocations);
554 assertWellFormedRoute(ptRelation);
555 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay(
556 splitWay,
557 SplitWayCommand.buildSplitChunks(splitWay, splitLocations),
558 new ArrayList<>(),
559 Strategy.keepLongestChunk(),
560 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY
561 );
562 assertTrue(result.isPresent());
563 result.get().executeCommand();
564 // Actual check
565 assertWellFormedRoute(ptRelation);
566 }
567
568 private static void assertWellFormedRoute(Relation route) {
569 WayConnectionTypeCalculator connectionTypeCalculator = new WayConnectionTypeCalculator();
570 List<WayConnectionType> links = connectionTypeCalculator.updateLinks(route, route.getMembers());
571 // NONE is the default, and is most often found on incomplete ways
572 links.removeIf(link -> link.direction == WayConnectionType.Direction.NONE);
573 assertAll("All links should be connected (forward)",
574 links.subList(0, links.size() - 2).stream().map(link -> () -> assertTrue(link.linkNext)));
575 assertAll("All links should be connected (backward)",
576 links.subList(1, links.size() - 1).stream().map(link -> () -> assertTrue(link.linkPrev)));
577 }
578}
Note: See TracBrowser for help on using the repository browser.