Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/command/SplitWayCommand.java
r16302 r16781 355 355 // If there are relations that cannot be split properly without downloading more members, 356 356 // present the user with an option to do so, or to abort the split. 357 List<Relation> relationsNeedingMoreMembers = new ArrayList<>();357 Set<Relation> relationsNeedingMoreMembers = new HashSet<>(); 358 358 Set<OsmPrimitive> incompleteMembers = new HashSet<>(); 359 359 for (RelationAnalysis relationAnalysis : analysis.getRelationAnalyses()) { 360 if (!relationAnalysis.needsMoreMembers()) continue; 361 362 Relation relation = relationAnalysis.getRelation(); 363 int position = relationAnalysis.getPosition(); 364 int membersCount = relation.getMembersCount(); 365 366 // Mark the neighbouring members for downloading if these are ways too. 367 relationsNeedingMoreMembers.add(relation); 368 RelationMember rmPrev = position == 0 369 ? relation.getMember(membersCount - 1) 370 : relation.getMember(position - 1); 371 RelationMember rmNext = position == membersCount - 1 372 ? relation.getMember(0) 373 : relation.getMember(position + 1); 374 375 if (rmPrev != null && rmPrev.isWay()) { 376 incompleteMembers.add(rmPrev.getWay()); 377 } 378 if (rmNext != null && rmNext.isWay()) { 379 incompleteMembers.add(rmNext.getWay()); 360 if (!relationAnalysis.getNeededIncompleteMembers().isEmpty()) { 361 incompleteMembers.addAll(relationAnalysis.getNeededIncompleteMembers()); 362 relationsNeedingMoreMembers.add(relationAnalysis.getRelation()); 380 363 } 381 364 } … … 397 380 } else { 398 381 // Ask the user. 399 missingMemberStrategy = offerToDownloadMissingMembersIfNeeded(analysis, relationsNeedingMoreMembers );382 missingMemberStrategy = offerToDownloadMissingMembersIfNeeded(analysis, relationsNeedingMoreMembers.size()); 400 383 } 401 384 break; … … 469 452 boolean isOrderedRelation = "route".equals(type) || "multipolygon".equals(type) || "boundary".equals(type); 470 453 471 int ic = 0; 472 int ir = 0; 473 List<RelationMember> relationMembers = r.getMembers(); 474 for (RelationMember rm : relationMembers) { 454 for (int ir = 0; ir < r.getMembersCount(); ir++) { 455 RelationMember rm = r.getMember(ir); 475 456 if (rm.getMember() == way) { 476 457 boolean insert = true; … … 496 477 // Attempt to determine the direction the ways in the relation are ordered. 497 478 Direction direction = Direction.UNKNOWN; 479 Set<Way> missingWays = new HashSet<>(); 498 480 if (isOrderedRelation) { 499 481 if (way.lastNode() == way.firstNode()) { … … 501 483 direction = Direction.IRRELEVANT; 502 484 } else { 503 boolean previousWayMemberMissing = true;504 boolean nextWayMemberMissing = true;505 506 485 // For ordered relations, looking beyond the nearest neighbour members is not required, 507 486 // and can even cause the wrong direction to be guessed (with closed loops). 508 if (ir - 1 >= 0 && relationMembers.get(ir - 1).isWay()) { 509 Way w = relationMembers.get(ir - 1).getWay(); 510 if (!w.isIncomplete()) { 511 previousWayMemberMissing = false; 487 if (ir - 1 >= 0 && r.getMember(ir - 1).isWay()) { 488 Way w = r.getMember(ir - 1).getWay(); 489 if (w.isIncomplete()) 490 missingWays.add(w); 491 else { 512 492 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 513 493 direction = Direction.FORWARDS; … … 516 496 } 517 497 } 518 } else {519 previousWayMemberMissing = false;520 498 } 521 if (ir + 1 < relationMembers.size() && relationMembers.get(ir + 1).isWay()) { 522 Way w = relationMembers.get(ir + 1).getWay(); 523 if (!w.isIncomplete()) { 524 nextWayMemberMissing = false; 499 if (ir + 1 < r.getMembersCount() && r.getMember(ir + 1).isWay()) { 500 Way w = r.getMember(ir + 1).getWay(); 501 if (w.isIncomplete()) 502 missingWays.add(w); 503 else { 525 504 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 526 505 direction = Direction.BACKWARDS; … … 529 508 } 530 509 } 531 } else {532 nextWayMemberMissing = false;533 510 } 534 511 535 if (direction == Direction.UNKNOWN 536 && !previousWayMemberMissing 537 && !nextWayMemberMissing) { 538 // If both the next and previous way member in the relation are already known at 539 // this point, and they are not connected to this one, then we can safely 540 // assume that the direction doesn't matter. Downloading any more members 541 // won't help in any case. 542 direction = Direction.IRRELEVANT; 543 } 544 if (direction == Direction.UNKNOWN && !way.getDataSet().getDataSourceBounds().isEmpty() 545 && !(way.firstNode().isOutsideDownloadArea() 546 || way.lastNode().isOutsideDownloadArea())) { 547 // we know the connected ways, downloading more members will not help 512 if (direction == Direction.UNKNOWN && missingWays.isEmpty()) { 513 // we cannot detect the direction and no way is missing. 514 // We can safely assume that the direction doesn't matter. 548 515 direction = Direction.IRRELEVANT; 549 516 } … … 551 518 } else { 552 519 int k = 1; 553 while (ir - k >= 0 || ir + k < r elationMembers.size()) {554 if (ir - k >= 0 && r elationMembers.get(ir - k).isWay()) {555 Way w = r elationMembers.get(ir - k).getWay();520 while (ir - k >= 0 || ir + k < r.getMembersCount()) { 521 if (ir - k >= 0 && r.getMember(ir - k).isWay()) { 522 Way w = r.getMember(ir - k).getWay(); 556 523 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 557 524 direction = Direction.FORWARDS; … … 561 528 break; 562 529 } 563 if (ir + k < r elationMembers.size() && relationMembers.get(ir + k).isWay()) {564 Way w = r elationMembers.get(ir + k).getWay();530 if (ir + k < r.getMembersCount() && r.getMember(ir + k).isWay()) { 531 Way w = r.getMember(ir + k).getWay(); 565 532 if (w.lastNode() == way.firstNode() || w.firstNode() == way.firstNode()) { 566 533 direction = Direction.BACKWARDS; … … 574 541 } 575 542 576 // We don't have enough information to determine the order of the new ways in this relation. 577 // This may cause relations to be saved with the two new way sections in reverse order. 578 // 579 // This often breaks routes. 580 // 581 // The user should be asked to download more members, or to abort the split operation. 582 boolean needsMoreMembers = isOrderedRelation 583 && direction == Direction.UNKNOWN 584 && relationMembers.size() > 1 585 && r.hasIncompleteMembers(); 586 587 relationAnalyses.add(new RelationAnalysis(c, rm, direction, needsMoreMembers, ic)); 588 ic += indexOfWayToKeep; 543 if (direction == Direction.UNKNOWN) { 544 // We don't have enough information to determine the order of the new ways in this relation. 545 // This may cause relations to be saved with the two new way sections in reverse order. 546 // 547 // This often breaks routes. 548 // 549 } else { 550 missingWays = Collections.emptySet(); 551 } 552 relationAnalyses.add(new RelationAnalysis(c, rm, direction, missingWays)); 589 553 } 590 554 } 591 ic++;592 ir++;593 555 } 594 556 … … 635 597 636 598 static MissingMemberStrategy offerToDownloadMissingMembersIfNeeded(Analysis analysis, 637 List<Relation> relationsNeedingMoreMembers) {599 int numRelationsNeedingMoreMembers) { 638 600 String[] options = { 639 601 tr("Yes, download the missing members"), … … 652 614 if (analysis.getNumberOfRelations() == 1) { 653 615 msgReferToRelations = tr("this relation"); 654 } else if (analysis.getNumberOfRelations() == relationsNeedingMoreMembers.size()) {616 } else if (analysis.getNumberOfRelations() == numRelationsNeedingMoreMembers) { 655 617 msgReferToRelations = tr("these relations"); 656 618 } else { … … 658 620 "one relation", 659 621 "{0} relations", 660 relationsNeedingMoreMembers.size(),661 relationsNeedingMoreMembers.size()622 numRelationsNeedingMoreMembers, 623 numRelationsNeedingMoreMembers 662 624 ); 663 625 } … … 733 695 Relation relation = relationAnalysis.getRelation(); 734 696 Direction direction = relationAnalysis.getDirection(); 735 int position = relationAnalysis.getPosition(); 697 698 int position = -1; 699 for (int i = 0; i < relation.getMembersCount(); i++) { 700 // search for identical member (can't use indexOf() as it uses equals() 701 if (rm == relation.getMember(i)) { 702 position = i; 703 break; 704 } 705 } 706 707 // sanity check 708 if (position < 0) { 709 throw new AssertionError("Relation member not found"); 710 } 736 711 737 712 int j = position; … … 918 893 private final RelationMember relationMember; 919 894 private final Direction direction; 920 private final boolean needsMoreMembers; 921 private final int position; 895 private final Set<Way> neededIncompleteMembers; 922 896 923 897 RelationAnalysis(Relation relation, 924 898 RelationMember relationMember, 925 899 Direction direction, 926 boolean needsMoreMembers, 927 int position) { 900 Set<Way> neededIncompleteMembers) { 928 901 this.relation = relation; 929 902 this.relationMember = relationMember; 930 903 this.direction = direction; 931 this.needsMoreMembers = needsMoreMembers; 932 this.position = position; 904 this.neededIncompleteMembers = neededIncompleteMembers; 933 905 } 934 906 … … 941 913 } 942 914 943 boolean needsMoreMembers() {944 return need sMoreMembers;915 public Set<Way> getNeededIncompleteMembers() { 916 return neededIncompleteMembers; 945 917 } 946 918 947 919 Relation getRelation() { 948 920 return relation; 949 }950 951 int getPosition() {952 return position;953 921 } 954 922 } -
trunk/test/unit/org/openstreetmap/josm/command/SplitWayCommandTest.java
r16200 r16781 367 367 } 368 368 } 369 370 /** 371 * Non-regression test for issue #19432 (AIOOB: Problem with member check with duplicate members) 372 * 373 * @throws IOException if any I/O error occurs 374 * @throws IllegalDataException if OSM parsing fails 375 */ 376 @Test 377 public void testTicket19432() throws IOException, IllegalDataException { 378 try (InputStream is = TestUtils.getRegressionDataStream(19432, "josm_split_way_exception_example.osm.bz2")) { 379 DataSet ds = OsmReader.parseDataSet(is, null); 380 381 Way splitWay = (Way) ds.getPrimitiveById(632576744L, OsmPrimitiveType.WAY); 382 Node splitNode = (Node) ds.getPrimitiveById(1523436358L, OsmPrimitiveType.NODE); 383 384 final Optional<SplitWayCommand> result = SplitWayCommand.splitWay( 385 splitWay, 386 SplitWayCommand.buildSplitChunks(splitWay, Collections.singletonList(splitNode)), 387 new ArrayList<>(), 388 Strategy.keepLongestChunk(), 389 // This split requires no additional downloads. If any are needed, this command will fail. 390 SplitWayCommand.WhenRelationOrderUncertain.SPLIT_ANYWAY 391 ); 392 393 // Should not result in aborting the split. 394 assertTrue(result.isPresent()); 395 } 396 } 369 397 }
Note:
See TracChangeset
for help on using the changeset viewer.