- Timestamp:
- 2010-08-18T17:29:56+02:00 (15 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/actions
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/CombineWayAction.java
r3409 r3445 15 15 import java.util.HashMap; 16 16 import java.util.HashSet; 17 import java.util.LinkedHashMap; 18 import java.util.LinkedHashSet; 17 19 import java.util.LinkedList; 18 20 import java.util.List; … … 113 115 return null; 114 116 ways.remove(null); // just in case - remove all null ways from the collection 115 ways = new HashSet<Way>(ways); // remove duplicates 117 118 // remove duplicates, preserving order 119 ways = new LinkedHashSet<Way>(ways); 116 120 117 121 // try to build a new way which includes all the combined … … 474 478 475 479 protected void prepare() { 476 Set<NodePair> undirectedEdges = new HashSet<NodePair>(); 477 successors = new HashMap<Node, List<NodePair>>(); 478 predecessors = new HashMap<Node, List<NodePair>>(); 480 Set<NodePair> undirectedEdges = new LinkedHashSet<NodePair>(); 481 successors = new LinkedHashMap<Node, List<NodePair>>(); 482 predecessors = new LinkedHashMap<Node, List<NodePair>>(); 479 483 480 484 for (NodePair pair: edges) { … … 489 493 490 494 public NodeGraph() { 491 edges = new HashSet<NodePair>(); 495 edges = new LinkedHashSet<NodePair>(); 492 496 } 493 497 … … 514 518 515 519 protected Set<Node> getTerminalNodes() { 516 Set<Node> ret = new HashSet<Node>(); 520 Set<Node> ret = new LinkedHashSet<Node>(); 517 521 for (Node n: getNodes()) { 518 522 if (isTerminalNode(n)) { … … 524 528 525 529 protected Set<Node> getNodes(Stack<NodePair> pairs) { 526 HashSet<Node> nodes = new HashSet<Node>(); 530 HashSet<Node> nodes = new LinkedHashSet<Node>(); 527 531 for (NodePair pair: pairs) { 528 532 nodes.add(pair.getA()); … … 544 548 545 549 protected Set<Node> getNodes() { 546 Set<Node> nodes = new HashSet<Node>(); 550 Set<Node> nodes = new LinkedHashSet<Node>(); 547 551 for (NodePair pair: edges) { 548 552 nodes.add(pair.getA()); -
trunk/src/org/openstreetmap/josm/actions/JoinAreasAction.java
r3383 r3445 7 7 8 8 import java.awt.GridBagLayout; 9 import java.awt.Polygon;10 9 import java.awt.event.ActionEvent; 11 10 import java.awt.event.KeyEvent; … … 16 15 import java.util.Collections; 17 16 import java.util.HashMap; 17 import java.util.HashSet; 18 18 import java.util.LinkedList; 19 19 import java.util.List; … … 31 31 32 32 import org.openstreetmap.josm.Main; 33 import org.openstreetmap.josm.actions.SplitWayAction.SplitWayResult; 33 34 import org.openstreetmap.josm.command.AddCommand; 34 35 import org.openstreetmap.josm.command.ChangeCommand; … … 55 56 private int cmdsCount = 0; 56 57 58 /** 59 * This helper class describes join ares action result. 60 * @author viesturs 61 * 62 */ 63 public static class JoinAreasResult { 64 65 public Way outerWay; 66 public List<Way> innerWays; 67 68 public boolean mergeSuccessful; 69 public boolean hasChanges; 70 public boolean hasRelationProblems; 71 } 72 57 73 // HelperClass 58 74 // Saves a node and two positions where to insert the node into the ways … … 107 123 RelationRole otherMember = (RelationRole) other; 108 124 return otherMember.role.equals(role) && otherMember.rel.equals(rel); 125 } 126 } 127 128 /** 129 * HelperClass 130 * saves a way and the "inside" side 131 * insideToTheLeft: if true left side is "in", false -right side is "in". 132 * Left and right are determined along the orientation of way. 133 */ 134 private static class WayInPath { 135 public final Way way; 136 public boolean insideToTheLeft; 137 138 public WayInPath(Way way, boolean insideLeft) { 139 this.way = way; 140 this.insideToTheLeft = insideLeft; 141 } 142 143 @Override 144 public int hashCode() { 145 return way.hashCode(); 146 } 147 148 @Override 149 public boolean equals(Object other) { 150 if (!(other instanceof WayInPath)) 151 return false; 152 WayInPath otherMember = (WayInPath) other; 153 return otherMember.way.equals(this.way) && otherMember.insideToTheLeft == this.insideToTheLeft; 109 154 } 110 155 } … … 164 209 } 165 210 166 if(joinAreas(ways.getFirst(), ways.getLast())) { 211 if (checkForTagConflicts(ways.getFirst(), ways.getLast())) { 212 //do nothing. //FIXME: abort? 213 } 214 215 JoinAreasResult result = joinAreas(ways.getFirst(), ways.getLast()); 216 217 if (result.hasChanges) { 167 218 Main.map.mapView.repaint(); 168 219 DataSet ds = Main.main.getCurrentDataSet(); … … 177 228 * @param Way First way/area 178 229 * @param Way Second way/area 179 * @return boolean Whether to display the "no operation" message 180 */ 181 private boolean joinAreas(Way a, Way b) { 230 */ 231 private JoinAreasResult joinAreas(Way a, Way b) { 232 233 JoinAreasResult result = new JoinAreasResult(); 234 result.hasChanges = false; 235 182 236 // Fix self-overlapping first or other errors 183 237 boolean same = a.equals(b); 184 boolean hadChanges = false;185 238 if(!same) { 186 239 int i = 0; 187 if(checkForTagConflicts(a, b)) return true; // User aborted, so don't warn again 188 if(joinAreas(a, a)) { 240 241 //join each area with itself, fixing self-crossings. 242 JoinAreasResult resultA = joinAreas(a, a); 243 JoinAreasResult resultB = joinAreas(b, b); 244 245 if (resultA.mergeSuccessful) { 246 a = resultA.outerWay; 189 247 ++i; 190 248 } 191 if(joinAreas(b, b)) { 249 if(resultB.mergeSuccessful) { 250 b = resultB.outerWay; 192 251 ++i; 193 252 } 194 hadChanges = i > 0; 253 254 result.hasChanges = i > 0; 195 255 cmdsCount = i; 196 256 } 197 257 198 ArrayList<OsmPrimitive> nodes = addIntersections(a, b); 199 if(nodes.size() == 0) return hadChanges; 258 ArrayList<Node> nodes = addIntersections(a, b); 259 260 //no intersections, return. 261 if(nodes.size() == 0) return result; 200 262 commitCommands(marktr("Added node on all intersections")); 201 263 … … 209 271 boolean warnAboutRelations = relations.size() > 0; 210 272 211 Collection<Way> allWays = splitWaysOnNodes(a, b, nodes);212 213 // Find all nodes andinner ways save them to a list214 Collection<Node> allNodes = getNodesFromWays(allWays);215 Collection<Way> innerWays = findInnerWays(allWays,allNodes);273 ArrayList<Way> allWays = splitWaysOnNodes(a, b, nodes); 274 275 // Find inner ways save them to a list 276 ArrayList<WayInPath> outerWays = findOuterWays(allWays); 277 ArrayList<Way> innerWays = findInnerWays(allWays, outerWays); 216 278 217 279 // Join outer ways 218 Way outerWay = joinOuterWays(allWays, innerWays); 219 if (outerWay == null) 220 return true; 280 Way outerWay = joinOuterWays(outerWays); 221 281 222 282 // Fix Multipolygons if there are any 223 Collection<Way> newInnerWays = fixMultipolygons(innerWays, outerWay, same);283 List<Way> newInnerWays = fixMultipolygons(innerWays, outerWay, same); 224 284 225 285 // Delete the remaining inner ways … … 235 295 236 296 stripTags(newInnerWays); 297 237 298 makeCommitsOneAction( 238 299 same … … 245 306 } 246 307 247 return true; 308 result.mergeSuccessful = true; 309 result.outerWay = outerWay; 310 result.innerWays = newInnerWays; 311 312 return result; 248 313 } 249 314 … … 331 396 * @return ArrayList<OsmPrimitive> List of new nodes 332 397 */ 333 private ArrayList< OsmPrimitive> addIntersections(Way a, Way b) {398 private ArrayList<Node> addIntersections(Way a, Way b) { 334 399 boolean same = a.equals(b); 335 400 int nodesSizeA = a.getNodesCount(); 336 401 int nodesSizeB = b.getNodesCount(); 337 402 338 // We use OsmPrimitive here instead of Node because we later need to split a way at these nodes. 339 // With OsmPrimitve we can simply add the way and don't have to loop over the nodes 340 ArrayList<OsmPrimitive> nodes = new ArrayList<OsmPrimitive>(); 403 ArrayList<Node> nodes = new ArrayList<Node>(); 341 404 ArrayList<NodeToSegs> nodesA = new ArrayList<NodeToSegs>(); 342 405 ArrayList<NodeToSegs> nodesB = new ArrayList<NodeToSegs>(); … … 489 552 490 553 /** 491 * This is a hacky implementation to make use of the splitWayAction code and 492 * should be improved. SplitWayAction needs to expose its splitWay function though. 493 */ 494 private Collection<Way> splitWaysOnNodes(Way a, Way b, Collection<OsmPrimitive> nodes) { 495 ArrayList<Way> ways = new ArrayList<Way>(); 554 * This method splits ways into smaller parts, using the prepared nodes list as split points. 555 * Uses SplitWayAction.splitWay for the heavy lifting. 556 * @return list of split ways (or original ways if no splitting is done). 557 */ 558 private ArrayList<Way> splitWaysOnNodes(Way a, Way b, Collection<Node> nodes) { 559 560 ArrayList<Way> result = new ArrayList<Way>(); 561 List<Way> ways = new ArrayList<Way>(); 496 562 ways.add(a); 497 if(!a.equals(b)) { 498 ways.add(b); 499 } 500 501 List<OsmPrimitive> affected = new ArrayList<OsmPrimitive>(); 502 for (Way way : ways) { 503 nodes.add(way); 504 Main.main.getCurrentDataSet().setSelected(nodes); 505 nodes.remove(way); 506 new SplitWayAction().actionPerformed(null); 507 cmdsCount++; 508 affected.addAll(Main.main.getCurrentDataSet().getSelectedWays()); 509 } 510 return osmprim2way(affected); 511 } 512 513 /** 514 * Converts a list of OsmPrimitives to a list of Ways 515 * @param Collection<OsmPrimitive> The OsmPrimitives list that's needed as a list of Ways 516 * @return Collection<Way> The list as list of Ways 517 */ 518 static private Collection<Way> osmprim2way(Collection<OsmPrimitive> ways) { 519 Collection<Way> result = new ArrayList<Way>(); 520 for(OsmPrimitive w: ways) { 521 if(w instanceof Way) { 522 result.add((Way) w); 523 } 524 } 563 ways.add(b); 564 565 for (Way way: ways) { 566 List<List<Node>> chunks = buildNodeChunks(way, nodes); 567 SplitWayResult split = SplitWayAction.splitWay(Main.map.mapView.getEditLayer(), way, chunks, Collections.<OsmPrimitive>emptyList()); 568 569 //execute the command, we need the results 570 Main.main.undoRedo.add(split.getCommand()); 571 cmdsCount ++; 572 573 result.add(split.getOriginalWay()); 574 result.addAll(split.getNewWays()); 575 } 576 577 return result; 578 } 579 580 /** 581 * Simple chunking version. Does not care about circular ways and result being proper, we will glue it all back together later on. 582 * @param way the way to chunk 583 * @param splitNodes the places where to cut. 584 * @return list of node segments to produce. 585 */ 586 private List<List<Node>> buildNodeChunks(Way way, Collection<Node> splitNodes) 587 { 588 List<List<Node>> result = new ArrayList<List<Node>>(); 589 List<Node> curList = new ArrayList<Node>(); 590 591 for(Node node: way.getNodes()){ 592 curList.add(node); 593 if (curList.size() > 1 && splitNodes.contains(node)){ 594 result.add(curList); 595 curList = new ArrayList<Node>(); 596 curList.add(node); 597 } 598 } 599 600 if (curList.size() > 1) 601 { 602 result.add(curList); 603 } 604 525 605 return result; 526 606 } … … 540 620 541 621 /** 542 * Finds all inner ways for a given list of Ways and Nodes from a multigon by constructing a polygon 543 * for each way, looking for inner nodes that are not part of this way. If a node is found, all ways 544 * containing this node are added to the list 622 * Gets all inner ways given all ways and outer ways. 623 * @param multigonWays 624 * @param outerWays 625 * @return list of inner ways. 626 */ 627 private ArrayList<Way> findInnerWays(Collection<Way> multigonWays, Collection<WayInPath> outerWays) { 628 ArrayList<Way> innerWays = new ArrayList<Way>(); 629 Set<Way> outerSet = new HashSet<Way>(); 630 631 for(WayInPath w: outerWays) { 632 outerSet.add(w.way); 633 } 634 635 for(Way way: multigonWays) { 636 if (!outerSet.contains(way)) { 637 innerWays.add(way); 638 } 639 } 640 641 return innerWays; 642 } 643 644 645 /** 646 * Finds all ways for a given list of Ways that form the outer hull. 647 * This works by starting with one node and traversing the multigon clockwise, always picking the leftmost path. 648 * Prerequisites - the ways must not intersect and have common end nodes where they meet. 545 649 * @param Collection<Way> A list of (splitted) ways that form a multigon 546 * @param Collection<Node> A list of nodes that belong to the multigon 547 * @return Collection<Way> A list of ways that are positioned inside the outer borders of the multigon 548 */ 549 private Collection<Way> findInnerWays(Collection<Way> multigonWays, Collection<Node> multigonNodes) { 550 Collection<Way> innerWays = new ArrayList<Way>(); 551 for(Way w: multigonWays) { 552 Polygon poly = new Polygon(); 553 for(Node n: (w).getNodes()) { 554 poly.addPoint(latlonToXY(n.getCoor().lat()), latlonToXY(n.getCoor().lon())); 555 } 556 557 for(Node n: multigonNodes) { 558 if(!(w).containsNode(n) && poly.contains(latlonToXY(n.getCoor().lat()), latlonToXY(n.getCoor().lon()))) { 559 getWaysByNode(innerWays, multigonWays, n); 560 } 561 } 562 } 563 564 return innerWays; 565 } 566 567 // Polygon only supports int coordinates, so convert them 568 private int latlonToXY(double val) { 569 return (int)Math.round(val*1000000); 570 } 571 572 /** 573 * Finds all ways that contain the given node. 574 * @param Collection<Way> A list to which matching ways will be added 575 * @param Collection<Way> A list of ways to check 576 * @param Node The node the ways should be checked against 577 */ 578 private void getWaysByNode(Collection<Way> innerWays, Collection<Way> w, Node n) { 579 for(Way way : w) { 580 if(!(way).containsNode(n)) { 650 * @return Collection<Way> A list of ways that form the outer boundary of the multigon. 651 */ 652 private static ArrayList<WayInPath> findOuterWays(Collection<Way> multigonWays) { 653 654 //find the node with minimum lat - it's guaranteed to be outer. (What about the south pole?) 655 Way bestWay = null; 656 Node topNode = null; 657 int topIndex = 0; 658 double minLat = Double.POSITIVE_INFINITY; 659 660 for(Way way: multigonWays) { 661 for (int pos = 0; pos < way.getNodesCount(); pos ++) { 662 Node node = way.getNode(pos); 663 664 if (node.getCoor().lat() < minLat) { 665 minLat = node.getCoor().lat(); 666 bestWay = way; 667 topNode = node; 668 topIndex = pos; 669 } 670 } 671 } 672 673 //get two final nodes from best way to mark as starting point and orientation. 674 Node headNode = null; 675 Node prevNode = null; 676 677 if (topNode.equals(bestWay.firstNode()) || topNode.equals(bestWay.lastNode())) { 678 //node is in split point 679 headNode = topNode; 680 //make a fake node that is downwards from head node (smaller latitude). It will be a division point between paths. 681 prevNode = new Node(new LatLon(headNode.getCoor().lat() - 1000, headNode.getCoor().lon())); 682 } else { 683 //node is inside way - pick the clockwise going end. 684 Node prev = bestWay.getNode(topIndex - 1); 685 Node next = bestWay.getNode(topIndex + 1); 686 687 if (angleIsClockwise(prev, topNode, next)) { 688 headNode = bestWay.lastNode(); 689 prevNode = bestWay.getNode(bestWay.getNodesCount() - 2); 690 } 691 else { 692 headNode = bestWay.firstNode(); 693 prevNode = bestWay.getNode(1); 694 } 695 } 696 697 Set<Way> outerWays = new HashSet<Way>(); 698 ArrayList<WayInPath> result = new ArrayList<WayInPath>(); 699 700 //iterate till full circle is reached 701 while (true) { 702 703 bestWay = null; 704 Node bestWayNextNode = null; 705 boolean bestWayReverse = false; 706 707 for (Way way: multigonWays) { 708 boolean wayReverse; 709 Node nextNode; 710 711 if (way.firstNode().equals(headNode)) { 712 //start adjacent to headNode 713 nextNode = way.getNode(1); 714 wayReverse = false; 715 716 if (nextNode.equals(prevNode)) { 717 //this is the path we came from - ignore it. 718 } else if (bestWay == null || !isToTheRightSideOfLine(prevNode, headNode, bestWayNextNode, nextNode)) { 719 //the new way is better 720 bestWay = way; 721 bestWayReverse = wayReverse; 722 bestWayNextNode = nextNode; 723 } 724 } 725 726 if (way.lastNode().equals(headNode)) { 727 //end adjacent to headNode 728 nextNode = way.getNode(way.getNodesCount() - 2); 729 wayReverse = true; 730 731 if (nextNode.equals(prevNode)) { 732 //this is the path we came from - ignore it. 733 } else if (bestWay == null || !isToTheRightSideOfLine(prevNode, headNode, bestWayNextNode, nextNode)) { 734 //the new way is better 735 bestWay = way; 736 bestWayReverse = wayReverse; 737 bestWayNextNode = nextNode; 738 } 739 } 740 } 741 742 if (bestWay == null) 743 throw new RuntimeException(); 744 else if (outerWays.contains(bestWay)) 745 break; //full circle reached, terminate. 746 else { 747 //add to outer ways, repeat. 748 outerWays.add(bestWay); 749 result.add(new WayInPath(bestWay, bestWayReverse)); 750 headNode = bestWayReverse ? bestWay.firstNode() : bestWay.lastNode(); 751 prevNode = bestWayReverse ? bestWay.getNode(1) : bestWay.getNode(bestWay.getNodesCount() - 2); 752 } 753 } 754 755 return result; 756 } 757 758 /** 759 * Tests if given point is to the right side of path consisting of 3 points. 760 * @param lineP1 first point in path 761 * @param lineP2 second point in path 762 * @param lineP3 third point in path 763 * @param testPoint 764 * @return true if to the right side, false otherwise 765 */ 766 public static boolean isToTheRightSideOfLine(Node lineP1, Node lineP2, Node lineP3, Node testPoint) 767 { 768 boolean pathBendToRight = angleIsClockwise(lineP1, lineP2, lineP3); 769 boolean rightOfSeg1 = angleIsClockwise(lineP1, lineP2, testPoint); 770 boolean rightOfSeg2 = angleIsClockwise(lineP2, lineP3, testPoint); 771 772 if (pathBendToRight) 773 return rightOfSeg1 && rightOfSeg2; 774 else 775 return !(!rightOfSeg1 && !rightOfSeg2); 776 } 777 778 /** 779 * This method tests if secondNode is clockwise to first node. 780 * @param commonNode starting point for both vectors 781 * @param firstNode first vector end node 782 * @param secondNode second vector end node 783 * @return true if first vector is clockwise before second vector. 784 */ 785 public static boolean angleIsClockwise(Node commonNode, Node firstNode, Node secondNode) 786 { 787 double dla1 = (firstNode.getCoor().lat() - commonNode.getCoor().lat()); 788 double dla2 = (secondNode.getCoor().lat() - commonNode.getCoor().lat()); 789 double dlo1 = (firstNode.getCoor().lon() - commonNode.getCoor().lon()); 790 double dlo2 = (secondNode.getCoor().lon() - commonNode.getCoor().lon()); 791 792 return dla1 * dlo2 - dlo1 * dla2 > 0; 793 } 794 795 /** 796 * Tests if point is inside a polygon. The polygon can be self-intersecting. In such case the contains function works in xor-like manner. 797 * @param polygonNodes list of nodes from polygon path. 798 * @param point the point to test 799 * @return true if the point is inside polygon. 800 * FIXME: this should probably be moved to tools.. 801 */ 802 public static boolean nodeInsidePolygon(ArrayList<Node> polygonNodes, Node point) 803 { 804 if (polygonNodes.size() < 3) 805 return false; 806 807 boolean inside = false; 808 Node p1, p2; 809 810 //iterate each side of the polygon, start with the last segment 811 Node oldPoint = polygonNodes.get(polygonNodes.size() - 1); 812 813 for(Node newPoint: polygonNodes) 814 { 815 //skip duplicate points 816 if (newPoint.equals(oldPoint)) { 581 817 continue; 582 818 } 583 if(!innerWays.contains(way)) { 584 innerWays.add(way); // Will need this later for multigons 585 } 586 } 587 } 588 589 /** 590 * Joins the two outer ways and deletes all short ways that can't be part of a multipolygon anyway 591 * @param Collection<OsmPrimitive> The list of all ways that belong to that multigon 592 * @param Collection<Way> The list of inner ways that belong to that multigon 819 820 //order points so p1.lat <= p2.lat; 821 if (newPoint.getCoor().lat() > oldPoint.getCoor().lat()) 822 { 823 p1 = oldPoint; 824 p2 = newPoint; 825 } 826 else 827 { 828 p1 = newPoint; 829 p2 = oldPoint; 830 } 831 832 //test if the line is crossed and if so invert the inside flag. 833 if ((newPoint.getCoor().lat() < point.getCoor().lat()) == (point.getCoor().lat() <= oldPoint.getCoor().lat()) 834 && (point.getCoor().lon() - p1.getCoor().lon()) * (p2.getCoor().lat() - p1.getCoor().lat()) 835 < (p2.getCoor().lon() - p1.getCoor().lon()) * (point.getCoor().lat() - p1.getCoor().lat())) 836 { 837 inside = !inside; 838 } 839 840 oldPoint = newPoint; 841 } 842 843 return inside; 844 } 845 846 /** 847 * Joins the outer ways and deletes all short ways that can't be part of a multipolygon anyway. 848 * @param Collection<Way> The list of outer ways that belong to that multigon. 593 849 * @return Way The newly created outer way 594 850 */ 595 private Way joinOuterWays(Collection<Way> multigonWays, Collection<Way> innerWays) { 596 ArrayList<Way> join = new ArrayList<Way>(); 597 for(Way w: multigonWays) { 598 // Skip inner ways 599 if(innerWays.contains(w)) { 600 continue; 601 } 602 603 if(w.getNodesCount() <= 2) { 604 cmds.add(new DeleteCommand(w)); 605 } else { 606 join.add(w); 851 private Way joinOuterWays(ArrayList<WayInPath> outerWays) { 852 853 //leave original orientation, if all paths are reverse. 854 boolean allReverse = true; 855 for(WayInPath way: outerWays) { 856 allReverse &= way.insideToTheLeft; 857 } 858 859 if (allReverse) { 860 for(WayInPath way: outerWays){ 861 way.insideToTheLeft = !way.insideToTheLeft; 607 862 } 608 863 } 609 864 610 865 commitCommands(marktr("Join Areas: Remove Short Ways")); 611 Way joinedWay = join Ways(join);866 Way joinedWay = joinOrientedWays(outerWays); 612 867 if (joinedWay != null) 613 868 return closeWay(joinedWay); … … 633 888 634 889 /** 890 * Joins a list of ways (using CombineWayAction and ReverseWayAction as specified in WayInPath) 891 * @param ArrayList<Way> The list of ways to join and reverse 892 * @return Way The newly created way 893 */ 894 private Way joinOrientedWays(ArrayList<WayInPath> ways) { 895 if(ways.size() < 2) 896 return ways.get(0).way; 897 898 // This will turn ways so all of them point in the same direction and CombineAction won't bug 899 // the user about this. 900 901 List<Way> actionWays = new ArrayList<Way>(ways.size()); 902 903 for(WayInPath way : ways) { 904 actionWays.add(way.way); 905 906 if (way.insideToTheLeft) { 907 Main.main.getCurrentDataSet().setSelected(way.way); 908 new ReverseWayAction().actionPerformed(null); 909 cmdsCount++; 910 } 911 } 912 913 Way result = new CombineWayAction().combineWays(actionWays); 914 915 if(result != null) { 916 cmdsCount++; 917 } 918 return result; 919 } 920 921 /** 635 922 * Joins a list of ways (using CombineWayAction and ReverseWayAction if necessary to quiet the former) 636 923 * @param ArrayList<Way> The list of ways to join … … 638 925 */ 639 926 private Way joinWays(ArrayList<Way> ways) { 640 if(ways.size() < 2) return ways.get(0); 927 if(ways.size() < 2) 928 return ways.get(0); 641 929 642 930 // This will turn ways so all of them point in the same direction and CombineAction won't bug 643 931 // the user about this. 644 932 Way a = null; 645 for(Way b : ways) { 933 for (Way b : ways) { 646 934 if(a == null) { 647 935 a = b; … … 656 944 a = b; 657 945 } 658 if((a = new CombineWayAction().combineWays(ways)) != null) { 946 if ((a = new CombineWayAction().combineWays(ways)) != null) { 659 947 cmdsCount++; 660 948 }
Note:
See TracChangeset
for help on using the changeset viewer.