- Timestamp:
- 2014-07-10T21:46:01+02:00 (10 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/JoinNodeWayAction.java
r7194 r7302 19 19 import java.awt.event.ActionEvent; 20 20 import java.awt.event.KeyEvent; 21 import java.util.Comparator; 21 22 import java.util.Collection; 22 23 import java.util.Collections; … … 24 25 import java.util.List; 25 26 import java.util.Map; 27 import java.util.HashMap; 26 28 import java.util.Set; 27 29 import java.util.SortedSet; … … 66 68 return; 67 69 Collection<Node> selectedNodes = getCurrentDataSet().getSelectedNodes(); 68 // Allow multiple selected nodes too?69 if (selectedNodes.size() != 1) return;70 71 final Node node = selectedNodes.iterator().next();72 73 70 Collection<Command> cmds = new LinkedList<>(); 71 Map<Way, MultiMap<Integer, Node>> data = new HashMap<>(); 74 72 75 73 // If the user has selected some ways, only join the node to these. … … 77 75 !getCurrentDataSet().getSelectedWays().isEmpty(); 78 76 79 List<WaySegment> wss = Main.map.mapView.getNearestWaySegments( 80 Main.map.mapView.getPoint(node), OsmPrimitive.isSelectablePredicate); 81 MultiMap<Way, Integer> insertPoints = new MultiMap<>(); 82 for (WaySegment ws : wss) { 83 // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive. 84 if (restrictToSelectedWays && !ws.way.isSelected()) { 85 continue; 86 } 87 88 if (ws.getFirstNode() != node && ws.getSecondNode() != node) { 89 insertPoints.put(ws.way, ws.lowerIndex); 90 } 91 } 92 93 for (Map.Entry<Way, Set<Integer>> entry : insertPoints.entrySet()) { 77 // Planning phase: decide where we'll insert the nodes and put it all in "data" 78 for (Node node : selectedNodes) { 79 List<WaySegment> wss = Main.map.mapView.getNearestWaySegments( 80 Main.map.mapView.getPoint(node), OsmPrimitive.isSelectablePredicate); 81 82 MultiMap<Way, Integer> insertPoints = new MultiMap<>(); 83 for (WaySegment ws : wss) { 84 // Maybe cleaner to pass a "isSelected" predicate to getNearestWaySegments, but this is less invasive. 85 if (restrictToSelectedWays && !ws.way.isSelected()) { 86 continue; 87 } 88 89 if (ws.getFirstNode() != node && ws.getSecondNode() != node) { 90 insertPoints.put(ws.way, ws.lowerIndex); 91 } 92 } 93 for (Map.Entry<Way, Set<Integer>> entry : insertPoints.entrySet()) { 94 final Way w = entry.getKey(); 95 final Set<Integer> insertPointsForWay = entry.getValue(); 96 for (int i : pruneSuccs(insertPointsForWay)) { 97 MultiMap<Integer, Node> innerMap; 98 if (!data.containsKey(w)) { 99 innerMap = new MultiMap<>(); 100 } else { 101 innerMap = data.get(w); 102 } 103 innerMap.put(i, node); 104 data.put(w, innerMap); 105 } 106 } 107 } 108 109 // Execute phase: traverse the structure "data" and finally put the nodes into place 110 for (Map.Entry<Way, MultiMap<Integer, Node>> entry : data.entrySet()) { 94 111 final Way w = entry.getKey(); 95 final Set<Integer> insertPointsForWay = entry.getValue(); 96 if (insertPointsForWay.isEmpty()) { 97 continue; 98 } 99 100 List<Node> nodesToAdd = w.getNodes(); 101 for (int i : pruneSuccsAndReverse(insertPointsForWay)) { 112 final MultiMap<Integer, Node> innerEntry = entry.getValue(); 113 114 List<Integer> segmentIndexes = new LinkedList<>(); 115 segmentIndexes.addAll(innerEntry.keySet()); 116 Collections.sort(segmentIndexes, Collections.reverseOrder()); 117 118 List<Node> wayNodes = w.getNodes(); 119 for (Integer segmentIndex : segmentIndexes) { 120 final Set<Node> nodesInSegment = innerEntry.get(segmentIndex); 102 121 if (joinWayToNode) { 103 EastNorth newPosition = Geometry.closestPointToSegment( 104 w.getNode(i).getEastNorth(), w.getNode(i + 1).getEastNorth(), node.getEastNorth()); 105 cmds.add(new MoveCommand(node, Projections.inverseProject(newPosition))); 106 } 107 nodesToAdd.add(i + 1, node); 122 for (Node node : nodesInSegment) { 123 EastNorth newPosition = Geometry.closestPointToSegment(w.getNode(segmentIndex).getEastNorth(), 124 w.getNode(segmentIndex+1).getEastNorth(), 125 node.getEastNorth()); 126 cmds.add(new MoveCommand(node, Projections.inverseProject(newPosition))); 127 } 128 } 129 List<Node> nodesToAdd = new LinkedList<>(); 130 nodesToAdd.addAll(nodesInSegment); 131 Collections.sort(nodesToAdd, new NodeDistanceToRefNodeComparator(w.getNode(segmentIndex), w.getNode(segmentIndex+1), !joinWayToNode)); 132 wayNodes.addAll(segmentIndex + 1, nodesToAdd); 108 133 } 109 134 Way wnew = new Way(w); 110 wnew.setNodes( nodesToAdd);135 wnew.setNodes(wayNodes); 111 136 cmds.add(new ChangeCommand(w, wnew)); 112 137 } 138 113 139 if (cmds.isEmpty()) return; 114 140 Main.main.undoRedo.add(new SequenceCommand(getValue(NAME).toString(), cmds)); … … 116 142 } 117 143 118 private static SortedSet<Integer> pruneSuccs AndReverse(Collection<Integer> is) {119 SortedSet<Integer> is2 = new TreeSet<>( Collections.reverseOrder());144 private static SortedSet<Integer> pruneSuccs(Collection<Integer> is) { 145 SortedSet<Integer> is2 = new TreeSet<>(); 120 146 for (int i : is) { 121 147 if (!is2.contains(i - 1) && !is2.contains(i + 1)) { … … 124 150 } 125 151 return is2; 152 } 153 154 /** 155 * Sorts collinear nodes by their distance to a common reference node. 156 */ 157 private static class NodeDistanceToRefNodeComparator implements Comparator<Node> { 158 private final EastNorth refPoint; 159 private EastNorth refPoint2; 160 private final boolean projectToSegment; 161 NodeDistanceToRefNodeComparator(Node referenceNode) { 162 refPoint = referenceNode.getEastNorth(); 163 projectToSegment = false; 164 } 165 NodeDistanceToRefNodeComparator(Node referenceNode, Node referenceNode2, boolean projectFirst) { 166 refPoint = referenceNode.getEastNorth(); 167 refPoint2 = referenceNode2.getEastNorth(); 168 projectToSegment = projectFirst; 169 } 170 @Override 171 public int compare(Node first, Node second) { 172 EastNorth firstPosition = first.getEastNorth(); 173 EastNorth secondPosition = second.getEastNorth(); 174 175 if (projectToSegment) { 176 firstPosition = Geometry.closestPointToSegment(refPoint, refPoint2, firstPosition); 177 secondPosition = Geometry.closestPointToSegment(refPoint, refPoint2, secondPosition); 178 } 179 180 double distanceFirst = firstPosition.distance(refPoint); 181 double distanceSecond = secondPosition.distance(refPoint); 182 double difference = distanceFirst - distanceSecond; 183 184 if (difference > 0.0) return 1; 185 if (difference < 0.0) return -1; 186 return 0; 187 } 126 188 } 127 189
Note:
See TracChangeset
for help on using the changeset viewer.