Ticket #2343: Fix JoinAreas.patch
| File Fix JoinAreas.patch, 7.4 KB (added by , 17 years ago) |
|---|
-
utilsplugin/src/UtilsPlugin/JoinAreasAction.java
246 246 247 247 stripTags(newInnerWays); 248 248 makeCommitsOneAction( 249 a.equals(b)250 ? "Joined self-overlapping area " + a.getName()251 : "Joined overlapping areas " + a.getName() + " and " + b.getName()249 same 250 ? "Joined self-overlapping area" 251 : "Joined overlapping areas" 252 252 ); 253 253 254 254 if(warnAboutRelations) … … 541 541 542 542 for(Node n: multigonNodes) { 543 543 if(!((Way)w).nodes.contains(n) && poly.contains(latlonToXY(n.coor.lat()), latlonToXY(n.coor.lon()))) { 544 innerWays.addAll(getWaysByNode(multigonWays, n));544 getWaysByNode(innerWays, multigonWays, n); 545 545 } 546 546 } 547 547 } … … 556 556 557 557 /** 558 558 * Finds all ways that contain the given node. 559 * @param Collection<OsmPrimitive> A collection of OsmPrimitives, but only ways will be honored 559 * @param Collection<Way> A list to which matching ways will be added 560 * @param Collection<Way> A list of ways to check 560 561 * @param Node The node the ways should be checked against 561 * @return Collection<Way> A list of ways that contain the given node562 562 */ 563 private Collection<Way> getWaysByNode(Collection<Way> w, Node n) { 564 Collection<Way> deletedWays = new ArrayList<Way>(); 563 private void getWaysByNode(Collection<Way> innerWays, Collection<Way> w, Node n) { 565 564 for(Way way : w) { 566 565 if(!((Way)way).nodes.contains(n)) continue; 567 if(! deletedWays.contains(way)) deletedWays.add(way); // Will need this later for multigons566 if(!innerWays.contains(way)) innerWays.add(way); // Will need this later for multigons 568 567 } 569 return deletedWays;570 568 } 571 569 572 570 /** … … 588 586 } 589 587 590 588 commitCommands("Join Areas: Remove Short Ways"); 591 return joinWays(join);589 return closeWay(joinWays(join)); 592 590 } 593 591 594 592 /** 593 * Ensures a way is closed. If it isn't, last and first node are connected. 594 * @param Way the way to ensure it's closed 595 * @return Way The joined way. 596 */ 597 private Way closeWay(Way w) { 598 if(w.isClosed()) 599 return w; 600 Main.ds.setSelected(w); 601 Way wnew = new Way(w); 602 wnew.addNode(wnew.firstNode()); 603 cmds.add(new ChangeCommand(w, wnew)); 604 commitCommands("Closed Way"); 605 return (Way)(Main.ds.getSelectedWays().toArray())[0]; 606 } 607 608 /** 595 609 * Joins a list of ways (using CombineWayAction and ReverseWayAction if necessary to quiet the former) 596 610 * @param ArrayList<Way> The list of ways to join 597 611 * @return Way The newly created way 598 612 */ 599 613 private Way joinWays(ArrayList<Way> ways) { 600 614 if(ways.size() < 2) return ways.get(0); 601 //Main.ds.setSelected(ways);602 615 603 616 // This will turn ways so all of them point in the same direction and CombineAction won't bug 604 617 // the user about this. … … 617 630 a = b; 618 631 } 619 632 Main.ds.setSelected(ways); 633 // TODO: It might be possible that a confirmation dialog is presented even after reversing (for 634 // "strange" ways). If the user cancels this, makeCommitsOneAction will wrongly consume a previous 635 // action. Make CombineWayAction either silent or expose its combining capabilities. 620 636 new CombineWayAction().actionPerformed(null); 621 637 cmdsCount++; 622 638 return (Way)(Main.ds.getSelectedWays().toArray())[0]; … … 640 656 // Remaining nodes are those that contain to more than one way. All nodes that belong to an 641 657 // inner multigon part will have at least two ways, so we can use this to find which ways do 642 658 // belong to the multigon. 643 Collection<Way> possibleWays = new ArrayList<Way>();659 ArrayList<Way> possibleWays = new ArrayList<Way>(); 644 660 wayIterator: for(Way w : uninterestingWays) { 645 661 boolean hasInnerNodes = false; 646 662 for(Node n : w.nodes) { 647 663 if(outerNodes.contains(n)) continue wayIterator; 648 664 if(!hasInnerNodes && innerNodes.contains(n)) hasInnerNodes = true; 649 665 } 650 if(!hasInnerNodes && w.nodes.size() >=2) continue;666 if(!hasInnerNodes || w.nodes.size() < 2) continue; 651 667 possibleWays.add(w); 652 668 } 653 669 670 // This removes unnecessary ways that might have been added. 671 removeAlmostAlikeWays(possibleWays); 672 removePartlyUnconnectedWays(possibleWays); 673 654 674 // Join all ways that have one start/ending node in common 655 675 Way joined = null; 656 676 outerIterator: do { … … 687 707 } 688 708 689 709 /** 710 * Removes almost alike ways (= ways that are on top of each other for all nodes) 711 * @param ArrayList<Way> the ways to remove almost-duplicates from 712 */ 713 private void removeAlmostAlikeWays(ArrayList<Way> ways) { 714 Collection<Way> removables = new ArrayList<Way>(); 715 outer: for(int i=0; i < ways.size(); i++) { 716 Way a = ways.get(i); 717 for(int j=i+1; j < ways.size(); j++) { 718 Way b = ways.get(j); 719 List<Node> revNodes = new ArrayList<Node>(b.nodes); 720 Collections.reverse(revNodes); 721 if(a.nodes.equals(b.nodes) || a.nodes.equals(revNodes)) { 722 removables.add(a); 723 continue outer; 724 } 725 } 726 } 727 ways.removeAll(removables); 728 } 729 730 /** 731 * Removes ways from the given list whose starting or ending node doesn't 732 * connect to other ways from the same list (it's like removing spikes). 733 * @param ArrayList<Way> The list of ways to remove "spikes" from 734 */ 735 private void removePartlyUnconnectedWays(ArrayList<Way> ways) { 736 List<Way> removables = new ArrayList<Way>(); 737 for(Way a : ways) { 738 if(a.isClosed()) continue; 739 boolean connectedStart = false; 740 boolean connectedEnd = false; 741 for(Way b : ways) { 742 if(a.equals(b)) 743 continue; 744 if(b.isFirstLastNode(a.firstNode())) 745 connectedStart = true; 746 if(b.isFirstLastNode(a.lastNode())) 747 connectedEnd = true; 748 } 749 if(!connectedStart || !connectedEnd) 750 removables.add(a); 751 } 752 ways.removeAll(removables); 753 } 754 755 /** 690 756 * Checks if a way is collapsed (i.e. looks like <---->) 691 757 * @param Way A *closed* way to check if it is collapsed 692 758 * @return boolean If the closed way is collapsed or not … … 824 890 private void makeCommitsOneAction(String message) { 825 891 UndoRedoHandler ur = Main.main.undoRedo; 826 892 cmds.clear(); 827 for(int i = ur.commands.size() - cmdsCount; i < ur.commands.size(); i++) 893 int i = Math.max(ur.commands.size() - cmdsCount, 0); 894 for(; i < ur.commands.size(); i++) 828 895 cmds.add(ur.commands.get(i)); 829 896 830 for(i nt i = 0; i < cmdsCount; i++)897 for(i = 0; i < cmds.size(); i++) 831 898 ur.undo(); 832 899 833 900 commitCommands(message == null ? "Join Areas Function" : message);
