- Timestamp:
- 2007-10-26T10:21:22+02:00 (17 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/MergeNodesAction.java
r424 r428 39 39 import org.openstreetmap.josm.data.osm.Node; 40 40 import org.openstreetmap.josm.data.osm.NodePair; 41 import org.openstreetmap.josm.data.osm.visitor.CollectBackReferencesVisitor; 41 42 import org.openstreetmap.josm.tools.GBC; 42 43 … … 96 97 } 97 98 99 private static class RelationRolePair { 100 public Relation rel; 101 public String role; 102 103 public RelationRolePair(Relation rel, String role) { 104 this.rel = rel; 105 this.role = role; 106 } 107 108 @Override public boolean equals(Object o) { 109 return o instanceof RelationRolePair 110 && rel == ((RelationRolePair) o).rel 111 && role.equals(((RelationRolePair) o).role); 112 } 113 114 @Override public int hashCode() { 115 return rel.hashCode() ^ role.hashCode(); 116 } 117 } 118 98 119 /** 99 120 * really do the merging - returns the node that is left … … 102 123 Node newNode = new Node(dest); 103 124 104 // Check whether all ways have identical relationship membership. More 125 // Check whether all ways have identical relationship membership. More 105 126 // specifically: If one of the selected ways is a member of relation X 106 127 // in role Y, then all selected ways must be members of X in role Y. 107 128 108 // FIXME: In a later revision, we should display some sort of conflict 129 // FIXME: In a later revision, we should display some sort of conflict 109 130 // dialog like we do for tags, to let the user choose which relations 110 131 // should be kept. 111 132 112 // Step 1, iterate over all relations and create counters indicating113 // how many of the selected ways are part of relation X in role Y114 // (hashMap backlinks contains keys formed like X@Y)115 HashMap<String, Integer> backlinks = new HashMap<String, Integer>();133 // Step 1, iterate over all relations and figure out which of our 134 // selected ways are members of a relation. 135 HashMap<RelationRolePair, HashSet<Node>> backlinks = 136 new HashMap<RelationRolePair, HashSet<Node>>(); 116 137 HashSet<Relation> relationsUsingNodes = new HashSet<Relation>(); 117 138 for (Relation r : Main.ds.relations) { … … 119 140 for (RelationMember rm : r.members) { 120 141 if (rm.member instanceof Node) { 121 for (Node n : allNodes) {142 for (Node n : allNodes) { 122 143 if (rm.member == n) { 123 String hash = Long.toString(r.id) + "@" + rm.role;124 System.out.println(hash);125 if (backlinks.containsKey( hash)) {126 backlinks.put(hash, new Integer(backlinks.get(hash)+1));144 RelationRolePair pair = new RelationRolePair(r, rm.role); 145 HashSet<Node> nodelinks = new HashSet<Node>(); 146 if (backlinks.containsKey(pair)) { 147 nodelinks = backlinks.get(pair); 127 148 } else { 128 backlinks.put(hash, 1); 149 nodelinks = new HashSet<Node>(); 150 backlinks.put(pair, nodelinks); 129 151 } 152 nodelinks.add(n); 153 130 154 // this is just a cache for later use 131 155 relationsUsingNodes.add(r); … … 136 160 } 137 161 138 // Step 2, all values of the backlinks HashMap must now equal the size 139 // of the selection. 140 for (Integer i : backlinks.values()) { 141 if (i.intValue() != allNodes.size()) { 142 JOptionPane.showMessageDialog(Main.parent, tr("The selected nodes cannot be merged as they have differing relation memberships.")); 143 return null; 162 // Complain to the user if the ways don't have equal memberships. 163 for (HashSet<Node> nodelinks : backlinks.values()) { 164 if (!nodelinks.containsAll(allNodes)) { 165 int option = JOptionPane.showConfirmDialog(Main.parent, 166 tr("The selected nodes have differing relation memberships. " 167 + "Do you still want to merge them?"), 168 tr("Merge nodes with different memberships?"), 169 JOptionPane.YES_NO_OPTION); 170 if (option == JOptionPane.YES_OPTION) { 171 break; 172 } else { 173 return null; 174 } 144 175 } 145 176 } … … 181 212 cmds.add(new ChangeCommand(dest, newNode)); 182 213 183 // OK, now to merge the nodes - this should be fairly184 // straightforward:185 // for each node in allNodes that is not newNode, do:186 // search all existing ways and replace references of187 // current node with newNode, then delete current node188 189 214 Collection<OsmPrimitive> del = new HashSet<OsmPrimitive>(); 190 215 … … 213 238 } 214 239 if (nn.size() < 2) { 240 CollectBackReferencesVisitor backRefs = 241 new CollectBackReferencesVisitor(Main.ds, false); 242 w.visit(backRefs); 243 if (!backRefs.data.isEmpty()) { 244 JOptionPane.showMessageDialog(Main.parent, 245 tr("Cannot merge nodes: " + 246 "Would have to delete a way that is still used.")); 247 return null; 248 } 215 249 del.add(w); 216 250 } else { … … 223 257 224 258 // delete any merged nodes 225 for (Node n : allNodes) { 226 if (n != dest) { 227 del.add(n); 228 } 229 } 259 del.addAll(allNodes); 260 del.remove(dest); 230 261 if (!del.isEmpty()) cmds.add(new DeleteCommand(del)); 231 262 … … 234 265 Relation newRel = new Relation(r); 235 266 newRel.members.clear(); 267 HashSet<String> rolesToReAdd = new HashSet<String>(); 236 268 for (RelationMember rm : r.members) { 237 // only copy member if it is either the first of all the selected 238 // nodes (indexOf==0) or not one of the selected nodes (indexOf==-1) 239 if (allNodes.indexOf(rm.member) < 1) { 240 newRel.members.add(new RelationMember(rm)); 241 } 269 // Don't copy the member if it points to one of our nodes, 270 // just keep a note to re-add it later on. 271 if (allNodes.contains(rm.member)) { 272 rolesToReAdd.add(rm.role); 273 } else { 274 newRel.members.add(rm); 275 } 276 } 277 for (String role : rolesToReAdd) { 278 newRel.members.add(new RelationMember(role, dest)); 242 279 } 243 280 cmds.add(new ChangeCommand(r, newRel));
Note:
See TracChangeset
for help on using the changeset viewer.