Changeset 30782 in osm for applications/editors/josm/plugins/merge-overlap/src/mergeoverlap
- Timestamp:
- 2014-10-29T21:56:35+01:00 (11 years ago)
- Location:
- applications/editors/josm/plugins/merge-overlap/src/mergeoverlap
- Files:
-
- 4 edited
-
MergeOverlapAction.java (modified) (1 diff)
-
MergeOverlapPlugin.java (modified) (2 diffs)
-
hack/MyCombinePrimitiveResolverDialog.java (modified) (1 diff)
-
hack/MyRelationMemberConflictResolverModel.java (modified) (5 diffs)
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/MergeOverlapAction.java
r30766 r30782 50 50 * Merge overlapping part of ways. 51 51 */ 52 @SuppressWarnings("serial")53 52 public class MergeOverlapAction extends JosmAction { 54 53 55 public MergeOverlapAction() { 56 super(tr("Merge overlap"), "merge_overlap", 57 tr("Merge overlap of ways."), 58 Shortcut.registerShortcut("tools:mergeoverlap",tr("Tool: {0}", tr("Merge overlap")), KeyEvent.VK_O, 59 Shortcut.ALT_CTRL) 60 , true); 61 } 62 63 Map<Way, List<Relation>> relations = new HashMap<>(); 64 Map<Way, Way> oldWays = new HashMap<>(); 65 Map<Relation, Relation> newRelations = new HashMap<>(); 66 Set<Way> deletes = new HashSet<>(); 67 68 /** 69 * The action button has been clicked 70 * 71 * @param e 72 * Action Event 73 */ 54 /** 55 * Constructs a new {@code MergeOverlapAction}. 56 */ 57 public MergeOverlapAction() { 58 super(tr("Merge overlap"), "merge_overlap", 59 tr("Merge overlap of ways."), 60 Shortcut.registerShortcut("tools:mergeoverlap",tr("Tool: {0}", tr("Merge overlap")), KeyEvent.VK_O, 61 Shortcut.ALT_CTRL), true); 62 } 63 64 Map<Way, List<Relation>> relations = new HashMap<>(); 65 Map<Way, Way> oldWays = new HashMap<>(); 66 Map<Relation, Relation> newRelations = new HashMap<>(); 67 Set<Way> deletes = new HashSet<>(); 68 69 /** 70 * The action button has been clicked 71 * 72 * @param e 73 * Action Event 74 */ 75 @Override 76 public void actionPerformed(ActionEvent e) { 77 78 // List of selected ways 79 List<Way> ways = new ArrayList<>(); 80 relations.clear(); 81 newRelations.clear(); 82 83 // For every selected way 84 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { 85 if (osm instanceof Way && !osm.isDeleted()) { 86 Way way = (Way) osm; 87 ways.add(way); 88 List<Relation> rels = new ArrayList<>(); 89 for (Relation r : OsmPrimitive.getFilteredList(way.getReferrers(), Relation.class)) { 90 rels.add(r); 91 } 92 relations.put(way, rels); 93 } 94 } 95 96 List<Way> sel = new ArrayList<>(ways); 97 Collection<Command> cmds = new LinkedList<>(); 98 99 // ***** 100 // split 101 // ***** 102 for (Way way : ways) { 103 Set<Node> nodes = new HashSet<>(); 104 for (Way opositWay : ways) { 105 if (way != opositWay) { 106 List<NodePos> nodesPos = new LinkedList<>(); 107 108 int pos = 0; 109 for (Node node : way.getNodes()) { 110 int opositPos = 0; 111 for (Node opositNode : opositWay.getNodes()) { 112 if (node == opositNode) { 113 if (opositWay.isClosed()) { 114 opositPos %= opositWay.getNodesCount() - 1; 115 } 116 nodesPos.add(new NodePos(node, pos, opositPos)); 117 break; 118 } 119 opositPos++; 120 } 121 pos++; 122 } 123 124 NodePos start = null; 125 NodePos end = null; 126 int increment = 0; 127 128 boolean hasFirst = false; 129 for (NodePos node : nodesPos) { 130 if (start == null) { 131 start = node; 132 } else { 133 if (end == null) { 134 if (follows(way, opositWay, start, node, 1)) { 135 end = node; 136 increment = +1; 137 } else if (follows(way, opositWay, start, node, -1)) { 138 end = node; 139 increment = -1; 140 } else { 141 start = node; 142 end = null; 143 } 144 } else { 145 if (follows(way, opositWay, end, node, increment)) { 146 end = node; 147 } else { 148 hasFirst = addNodes(start, end, way, nodes, hasFirst); 149 start = node; 150 end = null; 151 } 152 } 153 } 154 } 155 156 if (start != null && end != null) { 157 hasFirst = addNodes(start, end, way, nodes, hasFirst); 158 start = null; 159 end = null; 160 } 161 } 162 } 163 if (!nodes.isEmpty() && !way.isClosed() || nodes.size() >= 2) { 164 List<List<Node>> wayChunks = SplitWayAction.buildSplitChunks(way, new ArrayList<>(nodes)); 165 SplitWayResult result = splitWay(getEditLayer(), way, wayChunks); 166 167 cmds.add(result.getCommand()); 168 sel.remove(way); 169 sel.add(result.getOriginalWay()); 170 sel.addAll(result.getNewWays()); 171 List<Relation> rels = relations.remove(way); 172 relations.put(result.getOriginalWay(), rels); 173 for (Way w : result.getNewWays()) { 174 relations.put(w, rels); 175 } 176 } 177 } 178 179 // ***** 180 // merge 181 // ***** 182 ways = new ArrayList<>(sel); 183 while (!ways.isEmpty()) { 184 Way way = ways.get(0); 185 List<Way> combine = new ArrayList<>(); 186 combine.add(way); 187 for (Way opositWay : ways) { 188 if (way != opositWay 189 && way.getNodesCount() == opositWay.getNodesCount()) { 190 boolean equals1 = true; 191 for (int i = 0; i < way.getNodesCount(); i++) { 192 if (way.getNode(i) != opositWay.getNode(i)) { 193 equals1 = false; 194 break; 195 } 196 } 197 boolean equals2 = true; 198 for (int i = 0; i < way.getNodesCount(); i++) { 199 if (way.getNode(i) != opositWay.getNode(way 200 .getNodesCount() 201 - i - 1)) { 202 equals2 = false; 203 break; 204 } 205 } 206 if (equals1 || equals2) { 207 combine.add(opositWay); 208 } 209 } 210 } 211 ways.removeAll(combine); 212 if (combine.size() > 1) { 213 sel.removeAll(combine); 214 // combine 215 Pair<Way, List<Command>> combineResult; 216 try { 217 combineResult = combineWaysWorker(combine); 218 } catch (UserCancelException ex) { 219 return; 220 } 221 sel.add(combineResult.a); 222 cmds.addAll(combineResult.b); 223 } 224 } 225 226 for (Relation old : newRelations.keySet()) { 227 cmds.add(new ChangeCommand(old, newRelations.get(old))); 228 } 229 230 List<Way> del = new LinkedList<>(); 231 for (Way w : deletes) { 232 if (!w.isDeleted()) { 233 del.add(w); 234 } 235 } 236 if (!del.isEmpty()) { 237 cmds.add(new DeleteCommand(del)); 238 } 239 240 // Commit 241 Main.main.undoRedo.add(new SequenceCommand(tr("Merge Overlap (combine)"), cmds)); 242 getCurrentDataSet().setSelected(sel); 243 Main.map.repaint(); 244 245 relations.clear(); 246 newRelations.clear(); 247 oldWays.clear(); 248 } 249 250 private static class NodePos { 251 Node node; 252 int pos; 253 int opositPos; 254 255 NodePos(Node n, int p, int op) { 256 node = n; 257 pos = p; 258 opositPos = op; 259 } 260 74 261 @Override 75 public void actionPerformed(ActionEvent e) { 76 77 // List of selected ways 78 List<Way> ways = new ArrayList<>(); 79 relations.clear(); 80 newRelations.clear(); 81 82 // For every selected way 83 for (OsmPrimitive osm : Main.main.getCurrentDataSet().getSelected()) { 84 if (osm instanceof Way && !osm.isDeleted()) { 85 Way way = (Way) osm; 86 ways.add(way); 87 List<Relation> rels = new ArrayList<>(); 88 for (Relation r : OsmPrimitive.getFilteredList(way 89 .getReferrers(), Relation.class)) { 90 rels.add(r); 91 } 92 relations.put(way, rels); 93 } 94 } 95 96 List<Way> sel = new ArrayList<>(ways); 97 Collection<Command> cmds = new LinkedList<>(); 98 99 // ***** 100 // split 101 // ***** 102 for (Way way : ways) { 103 Set<Node> nodes = new HashSet<>(); 104 for (Way opositWay : ways) { 105 if (way != opositWay) { 106 List<NodePos> nodesPos = new LinkedList<>(); 107 108 int pos = 0; 109 for (Node node : way.getNodes()) { 110 int opositPos = 0; 111 for (Node opositNode : opositWay.getNodes()) { 112 if (node == opositNode) { 113 if (opositWay.isClosed()) { 114 opositPos %= opositWay.getNodesCount() - 1; 115 } 116 nodesPos.add(new NodePos(node, pos, opositPos)); 117 break; 118 } 119 opositPos++; 120 } 121 pos++; 122 } 123 124 NodePos start = null; 125 NodePos end = null; 126 int increment = 0; 127 128 boolean hasFirst = false; 129 for (NodePos node : nodesPos) { 130 if (start == null) { 131 start = node; 132 } else { 133 if (end == null) { 134 if (follows(way, opositWay, start, node, 1)) { 135 end = node; 136 increment = +1; 137 } else if (follows(way, opositWay, start, node, 138 -1)) { 139 end = node; 140 increment = -1; 141 } else { 142 start = node; 143 end = null; 144 } 145 } else { 146 if (follows(way, opositWay, end, node, 147 increment)) { 148 end = node; 149 } else { 150 hasFirst = addNodes(start, end, way, nodes, 151 hasFirst); 152 start = node; 153 end = null; 154 } 155 } 156 } 157 } 158 159 if (start != null && end != null) { 160 hasFirst = addNodes(start, end, way, nodes, hasFirst); 161 start = null; 162 end = null; 163 } 164 } 165 } 166 if (!nodes.isEmpty() && !way.isClosed() || nodes.size() >= 2) { 167 List<List<Node>> wayChunks = SplitWayAction.buildSplitChunks( 168 way, new ArrayList<>(nodes)); 169 SplitWayResult result = splitWay(getEditLayer(), way, wayChunks); 170 171 cmds.add(result.getCommand()); 172 sel.remove(way); 173 sel.add(result.getOriginalWay()); 174 sel.addAll(result.getNewWays()); 175 List<Relation> rels = relations.remove(way); 176 relations.put(result.getOriginalWay(), rels); 177 for (Way w : result.getNewWays()) { 178 relations.put(w, rels); 179 } 180 } 181 } 182 183 // ***** 184 // merge 185 // ***** 186 ways = new ArrayList<>(sel); 187 while (!ways.isEmpty()) { 188 Way way = ways.get(0); 189 List<Way> combine = new ArrayList<>(); 190 combine.add(way); 191 for (Way opositWay : ways) { 192 if (way != opositWay 193 && way.getNodesCount() == opositWay.getNodesCount()) { 194 boolean equals1 = true; 195 for (int i = 0; i < way.getNodesCount(); i++) { 196 if (way.getNode(i) != opositWay.getNode(i)) { 197 equals1 = false; 198 break; 199 } 200 } 201 boolean equals2 = true; 202 for (int i = 0; i < way.getNodesCount(); i++) { 203 if (way.getNode(i) != opositWay.getNode(way 204 .getNodesCount() 205 - i - 1)) { 206 equals2 = false; 207 break; 208 } 209 } 210 if (equals1 || equals2) { 211 combine.add(opositWay); 212 } 213 } 214 } 215 ways.removeAll(combine); 216 if (combine.size() > 1) { 217 sel.removeAll(combine); 218 // combine 219 Pair<Way, List<Command>> combineResult; 220 try { 221 combineResult = combineWaysWorker(combine); 222 } catch (UserCancelException e1) { 223 return; 224 } 225 sel.add(combineResult.a); 226 cmds.addAll(combineResult.b); 227 } 228 } 229 230 for (Relation old : newRelations.keySet()) { 231 cmds.add(new ChangeCommand(old, newRelations.get(old))); 232 } 233 234 List<Way> del = new LinkedList<>(); 235 for (Way w : deletes) { 236 if (!w.isDeleted()) { 237 del.add(w); 238 } 239 } 240 if (!del.isEmpty()) { 241 cmds.add(new DeleteCommand(del)); 242 } 243 244 // Commit 245 Main.main.undoRedo.add(new SequenceCommand( 246 tr("Merge Overlap (combine)"), cmds)); 247 getCurrentDataSet().setSelected(sel); 248 Main.map.repaint(); 249 250 relations.clear(); 251 newRelations.clear(); 252 oldWays.clear(); 253 } 254 255 private class NodePos { 256 Node node; 257 int pos; 258 int opositPos; 259 260 NodePos(Node n, int p, int op) { 261 node = n; 262 pos = p; 263 opositPos = op; 264 } 265 266 @Override 267 public String toString() { 268 return "NodePos: " + pos + ", " + opositPos + ", " + node; 269 } 270 } 271 272 private boolean addNodes(NodePos start, NodePos end, Way way, 273 Set<Node> nodes, boolean hasFirst) { 274 if (way.isClosed() 275 || (start.node != way.getNode(0) && start.node != way 276 .getNode(way.getNodesCount() - 1))) { 277 hasFirst = hasFirst || start.node == way.getNode(0); 278 nodes.add(start.node); 279 } 280 if (way.isClosed() 281 || (end.node != way.getNode(0) && end.node != way.getNode(way 282 .getNodesCount() - 1))) { 283 if (hasFirst && (end.node == way.getNode(way.getNodesCount() - 1))) { 284 nodes.remove(way.getNode(0)); 285 } else { 286 nodes.add(end.node); 287 } 288 } 289 return hasFirst; 290 } 291 292 private boolean follows(Way way1, Way way2, NodePos np1, NodePos np2, 293 int incr) { 294 if (way2.isClosed() && incr == 1 295 && np1.opositPos == way2.getNodesCount() - 2) { 296 return np2.pos == np1.pos + 1 && np2.opositPos == 0; 297 } else if (way2.isClosed() && incr == 1 && np1.opositPos == 0) { 298 return np2.pos == np1.pos && np2.opositPos == 0 299 || np2.pos == np1.pos + 1 && np2.opositPos == 1; 300 } else if (way2.isClosed() && incr == -1 && np1.opositPos == 0) { 301 return np2.pos == np1.pos && np2.opositPos == 0 302 || np2.pos == np1.pos + 1 303 && np2.opositPos == way2.getNodesCount() - 2; 304 } else { 305 return np2.pos == np1.pos + 1 306 && np2.opositPos == np1.opositPos + incr; 307 } 308 } 309 310 /** 311 * Splits a way 312 * 313 * @param layer 314 * @param way 315 * @param wayChunks 316 * @return 317 */ 318 private SplitWayResult splitWay(OsmDataLayer layer, Way way, 319 List<List<Node>> wayChunks) { 320 // build a list of commands, and also a new selection list 321 Collection<Command> commandList = new ArrayList<>(wayChunks 322 .size()); 323 324 Iterator<List<Node>> chunkIt = wayChunks.iterator(); 325 Collection<String> nowarnroles = Main.pref.getCollection( 326 "way.split.roles.nowarn", Arrays.asList(new String[] { "outer", 327 "inner", "forward", "backward" })); 328 329 // First, change the original way 330 Way changedWay = new Way(way); 331 oldWays.put(changedWay, way); 332 changedWay.setNodes(chunkIt.next()); 333 commandList.add(new ChangeCommand(way, changedWay)); 334 335 List<Way> newWays = new ArrayList<>(); 336 // Second, create new ways 337 while (chunkIt.hasNext()) { 338 Way wayToAdd = new Way(); 339 wayToAdd.setKeys(way.getKeys()); 340 newWays.add(wayToAdd); 341 wayToAdd.setNodes(chunkIt.next()); 342 commandList.add(new AddCommand(layer, wayToAdd)); 343 } 344 boolean warnmerole = false; 345 boolean warnme = false; 346 // now copy all relations to new way also 347 348 for (Relation r : getParentRelations(way)) { 349 if (!r.isUsable()) { 350 continue; 351 } 352 Relation c = null; 353 String type = r.get("type"); 354 if (type == null) { 355 type = ""; 356 } 357 358 int i_c = 0, i_r = 0; 359 List<RelationMember> relationMembers = r.getMembers(); 360 for (RelationMember rm : relationMembers) { 361 if (rm.isWay() && rm.getMember() == way) { 362 boolean insert = true; 363 if ("restriction".equals(type)) { 364 /* 365 * this code assumes the restriction is correct. No real 366 * error checking done 367 */ 368 String role = rm.getRole(); 369 if ("from".equals(role) || "to".equals(role)) { 370 OsmPrimitive via = null; 371 for (RelationMember rmv : r.getMembers()) { 372 if ("via".equals(rmv.getRole())) { 373 via = rmv.getMember(); 374 } 375 } 376 List<Node> nodes = new ArrayList<>(); 377 if (via != null) { 378 if (via instanceof Node) { 379 nodes.add((Node) via); 380 } else if (via instanceof Way) { 381 nodes.add(((Way) via).lastNode()); 382 nodes.add(((Way) via).firstNode()); 383 } 384 } 385 Way res = null; 386 for (Node n : nodes) { 387 if (changedWay.isFirstLastNode(n)) { 388 res = way; 389 } 390 } 391 if (res == null) { 392 for (Way wayToAdd : newWays) { 393 for (Node n : nodes) { 394 if (wayToAdd.isFirstLastNode(n)) { 395 res = wayToAdd; 396 } 397 } 398 } 399 if (res != null) { 400 if (c == null) { 401 c = getNew(r); 402 } 403 c.addMember(new RelationMember(role, res)); 404 c.removeMembersFor(way); 405 insert = false; 406 } 407 } else { 408 insert = false; 409 } 410 } else if (!"via".equals(role)) { 411 warnme = true; 412 } 413 } else if (!("route".equals(type)) 414 && !("multipolygon".equals(type))) { 415 warnme = true; 416 } 417 if (c == null) { 418 c = getNew(r); 419 } 420 421 if (insert) { 422 if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) { 423 warnmerole = true; 424 } 425 426 Boolean backwards = null; 427 int k = 1; 428 while (i_r - k >= 0 || i_r + k < relationMembers.size()) { 429 if ((i_r - k >= 0) 430 && relationMembers.get(i_r - k).isWay()) { 431 Way w = relationMembers.get(i_r - k).getWay(); 432 if ((w.lastNode() == way.firstNode()) 433 || w.firstNode() == way.firstNode()) { 434 backwards = false; 435 } else if ((w.firstNode() == way.lastNode()) 436 || w.lastNode() == way.lastNode()) { 437 backwards = true; 438 } 439 break; 440 } 441 if ((i_r + k < relationMembers.size()) 442 && relationMembers.get(i_r + k).isWay()) { 443 Way w = relationMembers.get(i_r + k).getWay(); 444 if ((w.lastNode() == way.firstNode()) 445 || w.firstNode() == way.firstNode()) { 446 backwards = true; 447 } else if ((w.firstNode() == way.lastNode()) 448 || w.lastNode() == way.lastNode()) { 449 backwards = false; 450 } 451 break; 452 } 453 k++; 454 } 455 456 int j = i_c; 457 for (Way wayToAdd : newWays) { 458 RelationMember em = new RelationMember( 459 rm.getRole(), wayToAdd); 460 j++; 461 if ((backwards != null) && backwards) { 462 c.addMember(i_c, em); 463 } else { 464 c.addMember(j, em); 465 } 466 } 467 i_c = j; 468 } 469 } 470 i_c++; 471 i_r++; 472 } 473 474 if (c != null) { 475 // commandList.add(new ChangeCommand(layer, r, c)); 476 newRelations.put(r, c); 477 } 478 } 479 if (warnmerole) { 480 JOptionPane 481 .showMessageDialog( 482 Main.parent, 483 tr("<html>A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"), 484 tr("Warning"), JOptionPane.WARNING_MESSAGE); 485 } else if (warnme) { 486 JOptionPane 487 .showMessageDialog( 488 Main.parent, 489 tr("<html>A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"), 490 tr("Warning"), JOptionPane.WARNING_MESSAGE); 491 } 492 493 return new SplitWayResult( 494 new SequenceCommand(tr("Split way"), commandList), null, 495 changedWay, newWays); 496 } 497 498 /** 499 * @param ways 500 * @return null if ways cannot be combined. Otherwise returns the combined 501 * ways and the commands to combine 502 * @throws UserCancelException 503 */ 504 private Pair<Way, List<Command>> combineWaysWorker(Collection<Way> ways) 505 throws UserCancelException { 506 507 // prepare and clean the list of ways to combine 508 if (ways == null || ways.isEmpty()) 509 return null; 510 ways.remove(null); // just in case - remove all null ways from the 511 // collection 512 513 // remove duplicates, preserving order 514 ways = new LinkedHashSet<>(ways); 515 516 // try to build a new way which includes all the combined ways 517 NodeGraph graph = NodeGraph.createUndirectedGraphFromNodeWays(ways); 518 List<Node> path = graph.buildSpanningPath(); 519 520 // check whether any ways have been reversed in the process 521 // and build the collection of tags used by the ways to combine 522 TagCollection wayTags = TagCollection.unionOfAllPrimitives(ways); 523 524 List<Way> reversedWays = new LinkedList<>(); 525 List<Way> unreversedWays = new LinkedList<>(); 526 for (Way w : ways) { 527 if ((path.indexOf(w.getNode(0)) + 1) == path.lastIndexOf(w 528 .getNode(1))) { 529 unreversedWays.add(w); 530 } else { 531 reversedWays.add(w); 532 } 533 } 534 // reverse path if all ways have been reversed 535 if (unreversedWays.isEmpty()) { 536 Collections.reverse(path); 537 unreversedWays = reversedWays; 538 reversedWays = null; 539 } 540 if ((reversedWays != null) && !reversedWays.isEmpty()) { 541 // filter out ways that have no direction-dependent tags 542 unreversedWays = ReverseWayTagCorrector 543 .irreversibleWays(unreversedWays); 544 reversedWays = ReverseWayTagCorrector 545 .irreversibleWays(reversedWays); 546 // reverse path if there are more reversed than unreversed ways with 547 // direction-dependent tags 548 if (reversedWays.size() > unreversedWays.size()) { 549 Collections.reverse(path); 550 List<Way> tempWays = unreversedWays; 551 unreversedWays = reversedWays; 552 reversedWays = tempWays; 553 } 554 // if there are still reversed ways with direction-dependent tags, 555 // reverse their tags 556 if (!reversedWays.isEmpty()) { 557 List<Way> unreversedTagWays = new ArrayList<>(ways); 558 unreversedTagWays.removeAll(reversedWays); 559 ReverseWayTagCorrector reverseWayTagCorrector = new ReverseWayTagCorrector(); 560 List<Way> reversedTagWays = new ArrayList<>(); 561 Collection<Command> changePropertyCommands = null; 562 for (Way w : reversedWays) { 563 Way wnew = new Way(w); 564 reversedTagWays.add(wnew); 565 changePropertyCommands = reverseWayTagCorrector.execute(w, 566 wnew); 567 } 568 if ((changePropertyCommands != null) 569 && !changePropertyCommands.isEmpty()) { 570 for (Command c : changePropertyCommands) { 571 c.executeCommand(); 572 } 573 } 574 wayTags = TagCollection.unionOfAllPrimitives(reversedTagWays); 575 wayTags.add(TagCollection 576 .unionOfAllPrimitives(unreversedTagWays)); 577 } 578 } 579 580 // create the new way and apply the new node list 581 Way targetWay = getTargetWay(ways); 582 Way modifiedTargetWay = new Way(targetWay); 583 modifiedTargetWay.setNodes(path); 584 585 TagCollection completeWayTags = new TagCollection(wayTags); 586 combineTigerTags(completeWayTags); 587 normalizeTagCollectionBeforeEditing(completeWayTags, ways); 588 TagCollection tagsToEdit = new TagCollection(completeWayTags); 589 completeTagCollectionForEditing(tagsToEdit); 590 591 MyCombinePrimitiveResolverDialog dialog = MyCombinePrimitiveResolverDialog 592 .getInstance(); 593 dialog.getTagConflictResolverModel().populate(tagsToEdit, 594 completeWayTags.getKeysWithMultipleValues()); 595 dialog.setTargetPrimitive(targetWay); 596 Set<Relation> parentRelations = getParentRelations(ways); 597 dialog.getRelationMemberConflictResolverModel().populate( 598 parentRelations, ways, oldWays); 599 dialog.prepareDefaultDecisions(); 600 601 // resolve tag conflicts if necessary 602 if (askForMergeTag(ways) || duplicateParentRelations(ways)) { 603 dialog.setVisible(true); 604 if (dialog.isCanceled()) 605 throw new UserCancelException(); 606 } 607 608 LinkedList<Command> cmds = new LinkedList<>(); 609 deletes.addAll(ways); 610 deletes.remove(targetWay); 611 612 cmds.add(new ChangeCommand(targetWay, modifiedTargetWay)); 613 cmds.addAll(dialog.buildWayResolutionCommands()); 614 dialog.buildRelationCorrespondance(newRelations, oldWays); 615 616 return new Pair<Way, List<Command>>(targetWay, cmds); 617 } 618 619 private static Way getTargetWay(Collection<Way> combinedWays) { 620 // init with an arbitrary way 621 Way targetWay = combinedWays.iterator().next(); 622 623 // look for the first way already existing on 624 // the server 625 for (Way w : combinedWays) { 626 targetWay = w; 627 if (!w.isNew()) { 628 break; 629 } 630 } 631 return targetWay; 632 } 633 634 /** 635 * @return has tag to be merged (=> ask) 636 */ 637 private static boolean askForMergeTag(Collection<Way> ways) { 638 for (Way way : ways) { 639 for (Way oposite : ways) { 640 for (String key : way.getKeys().keySet()) { 641 if (!"source".equals(key) && oposite.hasKey(key) 642 && !way.get(key).equals(oposite.get(key))) { 643 return true; 644 } 645 } 646 } 647 } 648 return false; 649 } 650 651 /** 652 * @return has duplicate parent relation 653 */ 654 private boolean duplicateParentRelations(Collection<Way> ways) { 655 Set<Relation> relations = new HashSet<>(); 656 for (Way w : ways) { 657 List<Relation> rs = getParentRelations(w); 658 for (Relation r : rs) { 659 if (relations.contains(r)) { 660 return true; 661 } 662 } 663 relations.addAll(rs); 664 } 665 return false; 666 } 667 668 /** 669 * Replies the set of referring relations 670 * 671 * @return the set of referring relations 672 */ 673 private List<Relation> getParentRelations(Way way) { 674 List<Relation> rels = new ArrayList<>(); 675 for (Relation r : relations.get(way)) { 676 if (newRelations.containsKey(r)) { 677 rels.add(newRelations.get(r)); 678 } else { 679 rels.add(r); 680 } 681 } 682 return rels; 683 } 684 685 private Relation getNew(Relation r) { 686 return getNew(r, newRelations); 687 } 688 689 public static Relation getNew(Relation r, 690 Map<Relation, Relation> newRelations) { 691 if (newRelations.containsValue(r)) { 692 return r; 693 } else { 694 Relation c = new Relation(r); 695 newRelations.put(r, c); 696 return c; 697 } 698 } 262 public String toString() { 263 return "NodePos: " + pos + ", " + opositPos + ", " + node; 264 } 265 } 266 267 private boolean addNodes(NodePos start, NodePos end, Way way, 268 Set<Node> nodes, boolean hasFirst) { 269 if (way.isClosed() || (start.node != way.getNode(0) && start.node != way.getNode(way.getNodesCount() - 1))) { 270 hasFirst = hasFirst || start.node == way.getNode(0); 271 nodes.add(start.node); 272 } 273 if (way.isClosed() || (end.node != way.getNode(0) && end.node != way.getNode(way.getNodesCount() - 1))) { 274 if (hasFirst && (end.node == way.getNode(way.getNodesCount() - 1))) { 275 nodes.remove(way.getNode(0)); 276 } else { 277 nodes.add(end.node); 278 } 279 } 280 return hasFirst; 281 } 282 283 private boolean follows(Way way1, Way way2, NodePos np1, NodePos np2, 284 int incr) { 285 if (way2.isClosed() && incr == 1 286 && np1.opositPos == way2.getNodesCount() - 2) { 287 return np2.pos == np1.pos + 1 && np2.opositPos == 0; 288 } else if (way2.isClosed() && incr == 1 && np1.opositPos == 0) { 289 return np2.pos == np1.pos && np2.opositPos == 0 290 || np2.pos == np1.pos + 1 && np2.opositPos == 1; 291 } else if (way2.isClosed() && incr == -1 && np1.opositPos == 0) { 292 return np2.pos == np1.pos && np2.opositPos == 0 293 || np2.pos == np1.pos + 1 294 && np2.opositPos == way2.getNodesCount() - 2; 295 } else { 296 return np2.pos == np1.pos + 1 297 && np2.opositPos == np1.opositPos + incr; 298 } 299 } 300 301 /** 302 * Splits a way 303 * 304 * @param layer 305 * @param way 306 * @param wayChunks 307 * @return 308 */ 309 private SplitWayResult splitWay(OsmDataLayer layer, Way way, 310 List<List<Node>> wayChunks) { 311 // build a list of commands, and also a new selection list 312 Collection<Command> commandList = new ArrayList<>(wayChunks 313 .size()); 314 315 Iterator<List<Node>> chunkIt = wayChunks.iterator(); 316 Collection<String> nowarnroles = Main.pref.getCollection( 317 "way.split.roles.nowarn", Arrays.asList(new String[] { "outer", 318 "inner", "forward", "backward" })); 319 320 // First, change the original way 321 Way changedWay = new Way(way); 322 oldWays.put(changedWay, way); 323 changedWay.setNodes(chunkIt.next()); 324 commandList.add(new ChangeCommand(way, changedWay)); 325 326 List<Way> newWays = new ArrayList<>(); 327 // Second, create new ways 328 while (chunkIt.hasNext()) { 329 Way wayToAdd = new Way(); 330 wayToAdd.setKeys(way.getKeys()); 331 newWays.add(wayToAdd); 332 wayToAdd.setNodes(chunkIt.next()); 333 commandList.add(new AddCommand(layer, wayToAdd)); 334 } 335 boolean warnmerole = false; 336 boolean warnme = false; 337 // now copy all relations to new way also 338 339 for (Relation r : getParentRelations(way)) { 340 if (!r.isUsable()) { 341 continue; 342 } 343 Relation c = null; 344 String type = r.get("type"); 345 if (type == null) { 346 type = ""; 347 } 348 349 int ic = 0, ir = 0; 350 List<RelationMember> relationMembers = r.getMembers(); 351 for (RelationMember rm : relationMembers) { 352 if (rm.isWay() && rm.getMember() == way) { 353 boolean insert = true; 354 if ("restriction".equals(type)) { 355 /* 356 * this code assumes the restriction is correct. No real 357 * error checking done 358 */ 359 String role = rm.getRole(); 360 if ("from".equals(role) || "to".equals(role)) { 361 OsmPrimitive via = null; 362 for (RelationMember rmv : r.getMembers()) { 363 if ("via".equals(rmv.getRole())) { 364 via = rmv.getMember(); 365 } 366 } 367 List<Node> nodes = new ArrayList<>(); 368 if (via != null) { 369 if (via instanceof Node) { 370 nodes.add((Node) via); 371 } else if (via instanceof Way) { 372 nodes.add(((Way) via).lastNode()); 373 nodes.add(((Way) via).firstNode()); 374 } 375 } 376 Way res = null; 377 for (Node n : nodes) { 378 if (changedWay.isFirstLastNode(n)) { 379 res = way; 380 } 381 } 382 if (res == null) { 383 for (Way wayToAdd : newWays) { 384 for (Node n : nodes) { 385 if (wayToAdd.isFirstLastNode(n)) { 386 res = wayToAdd; 387 } 388 } 389 } 390 if (res != null) { 391 if (c == null) { 392 c = getNew(r); 393 } 394 c.addMember(new RelationMember(role, res)); 395 c.removeMembersFor(way); 396 insert = false; 397 } 398 } else { 399 insert = false; 400 } 401 } else if (!"via".equals(role)) { 402 warnme = true; 403 } 404 } else if (!("route".equals(type)) 405 && !("multipolygon".equals(type))) { 406 warnme = true; 407 } 408 if (c == null) { 409 c = getNew(r); 410 } 411 412 if (insert) { 413 if (rm.hasRole() && !nowarnroles.contains(rm.getRole())) { 414 warnmerole = true; 415 } 416 417 Boolean backwards = null; 418 int k = 1; 419 while (ir - k >= 0 || ir + k < relationMembers.size()) { 420 if ((ir - k >= 0) 421 && relationMembers.get(ir - k).isWay()) { 422 Way w = relationMembers.get(ir - k).getWay(); 423 if ((w.lastNode() == way.firstNode()) 424 || w.firstNode() == way.firstNode()) { 425 backwards = false; 426 } else if ((w.firstNode() == way.lastNode()) 427 || w.lastNode() == way.lastNode()) { 428 backwards = true; 429 } 430 break; 431 } 432 if ((ir + k < relationMembers.size()) 433 && relationMembers.get(ir + k).isWay()) { 434 Way w = relationMembers.get(ir + k).getWay(); 435 if ((w.lastNode() == way.firstNode()) 436 || w.firstNode() == way.firstNode()) { 437 backwards = true; 438 } else if ((w.firstNode() == way.lastNode()) 439 || w.lastNode() == way.lastNode()) { 440 backwards = false; 441 } 442 break; 443 } 444 k++; 445 } 446 447 int j = ic; 448 for (Way wayToAdd : newWays) { 449 RelationMember em = new RelationMember( 450 rm.getRole(), wayToAdd); 451 j++; 452 if ((backwards != null) && backwards) { 453 c.addMember(ic, em); 454 } else { 455 c.addMember(j, em); 456 } 457 } 458 ic = j; 459 } 460 } 461 ic++; 462 ir++; 463 } 464 465 if (c != null) { 466 // commandList.add(new ChangeCommand(layer, r, c)); 467 newRelations.put(r, c); 468 } 469 } 470 if (warnmerole) { 471 JOptionPane.showMessageDialog( 472 Main.parent, 473 tr("<html>A role based relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"), 474 tr("Warning"), JOptionPane.WARNING_MESSAGE); 475 } else if (warnme) { 476 JOptionPane.showMessageDialog( 477 Main.parent, 478 tr("<html>A relation membership was copied to all new ways.<br>You should verify this and correct it when necessary.</html>"), 479 tr("Warning"), JOptionPane.WARNING_MESSAGE); 480 } 481 482 return new SplitWayResult( 483 new SequenceCommand(tr("Split way"), commandList), null, 484 changedWay, newWays); 485 } 486 487 /** 488 * @param ways 489 * @return null if ways cannot be combined. Otherwise returns the combined 490 * ways and the commands to combine 491 * @throws UserCancelException 492 */ 493 private Pair<Way, List<Command>> combineWaysWorker(Collection<Way> ways) 494 throws UserCancelException { 495 496 // prepare and clean the list of ways to combine 497 if (ways == null || ways.isEmpty()) 498 return null; 499 ways.remove(null); // just in case - remove all null ways from the 500 // collection 501 502 // remove duplicates, preserving order 503 ways = new LinkedHashSet<>(ways); 504 505 // try to build a new way which includes all the combined ways 506 NodeGraph graph = NodeGraph.createUndirectedGraphFromNodeWays(ways); 507 List<Node> path = graph.buildSpanningPath(); 508 509 // check whether any ways have been reversed in the process 510 // and build the collection of tags used by the ways to combine 511 TagCollection wayTags = TagCollection.unionOfAllPrimitives(ways); 512 513 List<Way> reversedWays = new LinkedList<>(); 514 List<Way> unreversedWays = new LinkedList<>(); 515 for (Way w : ways) { 516 if ((path.indexOf(w.getNode(0)) + 1) == path.lastIndexOf(w 517 .getNode(1))) { 518 unreversedWays.add(w); 519 } else { 520 reversedWays.add(w); 521 } 522 } 523 // reverse path if all ways have been reversed 524 if (unreversedWays.isEmpty()) { 525 Collections.reverse(path); 526 unreversedWays = reversedWays; 527 reversedWays = null; 528 } 529 if ((reversedWays != null) && !reversedWays.isEmpty()) { 530 // filter out ways that have no direction-dependent tags 531 unreversedWays = ReverseWayTagCorrector 532 .irreversibleWays(unreversedWays); 533 reversedWays = ReverseWayTagCorrector 534 .irreversibleWays(reversedWays); 535 // reverse path if there are more reversed than unreversed ways with 536 // direction-dependent tags 537 if (reversedWays.size() > unreversedWays.size()) { 538 Collections.reverse(path); 539 List<Way> tempWays = unreversedWays; 540 unreversedWays = reversedWays; 541 reversedWays = tempWays; 542 } 543 // if there are still reversed ways with direction-dependent tags, 544 // reverse their tags 545 if (!reversedWays.isEmpty()) { 546 List<Way> unreversedTagWays = new ArrayList<>(ways); 547 unreversedTagWays.removeAll(reversedWays); 548 ReverseWayTagCorrector reverseWayTagCorrector = new ReverseWayTagCorrector(); 549 List<Way> reversedTagWays = new ArrayList<>(); 550 Collection<Command> changePropertyCommands = null; 551 for (Way w : reversedWays) { 552 Way wnew = new Way(w); 553 reversedTagWays.add(wnew); 554 changePropertyCommands = reverseWayTagCorrector.execute(w, 555 wnew); 556 } 557 if ((changePropertyCommands != null) 558 && !changePropertyCommands.isEmpty()) { 559 for (Command c : changePropertyCommands) { 560 c.executeCommand(); 561 } 562 } 563 wayTags = TagCollection.unionOfAllPrimitives(reversedTagWays); 564 wayTags.add(TagCollection.unionOfAllPrimitives(unreversedTagWays)); 565 } 566 } 567 568 // create the new way and apply the new node list 569 Way targetWay = getTargetWay(ways); 570 Way modifiedTargetWay = new Way(targetWay); 571 modifiedTargetWay.setNodes(path); 572 573 TagCollection completeWayTags = new TagCollection(wayTags); 574 combineTigerTags(completeWayTags); 575 normalizeTagCollectionBeforeEditing(completeWayTags, ways); 576 TagCollection tagsToEdit = new TagCollection(completeWayTags); 577 completeTagCollectionForEditing(tagsToEdit); 578 579 MyCombinePrimitiveResolverDialog dialog = MyCombinePrimitiveResolverDialog.getInstance(); 580 dialog.getTagConflictResolverModel().populate(tagsToEdit, completeWayTags.getKeysWithMultipleValues()); 581 dialog.setTargetPrimitive(targetWay); 582 Set<Relation> parentRelations = getParentRelations(ways); 583 dialog.getRelationMemberConflictResolverModel().populate(parentRelations, ways, oldWays); 584 dialog.prepareDefaultDecisions(); 585 586 // resolve tag conflicts if necessary 587 if (askForMergeTag(ways) || duplicateParentRelations(ways)) { 588 dialog.setVisible(true); 589 if (dialog.isCanceled()) 590 throw new UserCancelException(); 591 } 592 593 List<Command> cmds = new LinkedList<>(); 594 deletes.addAll(ways); 595 deletes.remove(targetWay); 596 597 cmds.add(new ChangeCommand(targetWay, modifiedTargetWay)); 598 cmds.addAll(dialog.buildWayResolutionCommands()); 599 dialog.buildRelationCorrespondance(newRelations, oldWays); 600 601 return new Pair<>(targetWay, cmds); 602 } 603 604 private static Way getTargetWay(Collection<Way> combinedWays) { 605 // init with an arbitrary way 606 Way targetWay = combinedWays.iterator().next(); 607 608 // look for the first way already existing on the server 609 for (Way w : combinedWays) { 610 targetWay = w; 611 if (!w.isNew()) { 612 break; 613 } 614 } 615 return targetWay; 616 } 617 618 /** 619 * @return has tag to be merged (=> ask) 620 */ 621 private static boolean askForMergeTag(Collection<Way> ways) { 622 for (Way way : ways) { 623 for (Way oposite : ways) { 624 for (String key : way.getKeys().keySet()) { 625 if (!"source".equals(key) && oposite.hasKey(key) 626 && !way.get(key).equals(oposite.get(key))) { 627 return true; 628 } 629 } 630 } 631 } 632 return false; 633 } 634 635 /** 636 * @return has duplicate parent relation 637 */ 638 private boolean duplicateParentRelations(Collection<Way> ways) { 639 Set<Relation> relations = new HashSet<>(); 640 for (Way w : ways) { 641 List<Relation> rs = getParentRelations(w); 642 for (Relation r : rs) { 643 if (relations.contains(r)) { 644 return true; 645 } 646 } 647 relations.addAll(rs); 648 } 649 return false; 650 } 651 652 /** 653 * Replies the set of referring relations 654 * 655 * @return the set of referring relations 656 */ 657 private List<Relation> getParentRelations(Way way) { 658 List<Relation> rels = new ArrayList<>(); 659 for (Relation r : relations.get(way)) { 660 if (newRelations.containsKey(r)) { 661 rels.add(newRelations.get(r)); 662 } else { 663 rels.add(r); 664 } 665 } 666 return rels; 667 } 668 669 private Relation getNew(Relation r) { 670 return getNew(r, newRelations); 671 } 672 673 public static Relation getNew(Relation r, Map<Relation, Relation> newRelations) { 674 if (newRelations.containsValue(r)) { 675 return r; 676 } else { 677 Relation c = new Relation(r); 678 newRelations.put(r, c); 679 return c; 680 } 681 } 699 682 /* 700 private Way getOld(Way r) {701 return getOld(r, oldWays);702 }*/703 704 public static Way getOld(Way w, Map<Way, Way> oldWays) {705 if (oldWays.containsKey(w)) {706 return oldWays.get(w);707 } else {708 return w;709 }710 }711 712 /**713 * Replies the set of referring relations714 *715 * @return the set of referring relations716 */717 private Set<Relation> getParentRelations(Collection<Way> ways) {718 HashSet<Relation> ret = new HashSet<>();719 for (Way w : ways) {720 ret.addAll(getParentRelations(w));721 }722 return ret;723 }724 725 /** Enable this action only if something is selected */726 @Override727 protected void updateEnabledState() {728 if (getCurrentDataSet() == null) {729 setEnabled(false);730 } else {731 updateEnabledState(getCurrentDataSet().getSelected());732 }733 }734 735 /** Enable this action only if something is selected */736 @Override737 protected void updateEnabledState(738 Collection<? extends OsmPrimitive> selection) {739 if (selection == null) {740 setEnabled(false);741 return;742 }743 for (OsmPrimitive primitive : selection) {744 if (!(primitive instanceof Way) || primitive.isDeleted()) {745 setEnabled(false);746 return;747 }748 }749 setEnabled(selection.size() >= 2);750 }683 private Way getOld(Way r) { 684 return getOld(r, oldWays); 685 }*/ 686 687 public static Way getOld(Way w, Map<Way, Way> oldWays) { 688 if (oldWays.containsKey(w)) { 689 return oldWays.get(w); 690 } else { 691 return w; 692 } 693 } 694 695 /** 696 * Replies the set of referring relations 697 * 698 * @return the set of referring relations 699 */ 700 private Set<Relation> getParentRelations(Collection<Way> ways) { 701 Set<Relation> ret = new HashSet<>(); 702 for (Way w : ways) { 703 ret.addAll(getParentRelations(w)); 704 } 705 return ret; 706 } 707 708 /** Enable this action only if something is selected */ 709 @Override 710 protected void updateEnabledState() { 711 if (getCurrentDataSet() == null) { 712 setEnabled(false); 713 } else { 714 updateEnabledState(getCurrentDataSet().getSelected()); 715 } 716 } 717 718 /** Enable this action only if something is selected */ 719 @Override 720 protected void updateEnabledState( 721 Collection<? extends OsmPrimitive> selection) { 722 if (selection == null) { 723 setEnabled(false); 724 return; 725 } 726 for (OsmPrimitive primitive : selection) { 727 if (!(primitive instanceof Way) || primitive.isDeleted()) { 728 setEnabled(false); 729 return; 730 } 731 } 732 setEnabled(selection.size() >= 2); 733 } 751 734 } -
applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/MergeOverlapPlugin.java
r29778 r30782 1 1 package mergeoverlap; 2 3 import static org.openstreetmap.josm.tools.I18n.tr;4 2 5 3 import org.openstreetmap.josm.Main; … … 13 11 public class MergeOverlapPlugin extends Plugin { 14 12 15 protected String name; 16 13 /** 14 * Constructs a new {@code MergeOverlapPlugin}. 15 * @param info plugin information 16 */ 17 17 public MergeOverlapPlugin(PluginInformation info) { 18 18 super(info); 19 name = tr("Merge overlap");20 19 MainMenu.add(Main.main.menu.moreToolsMenu, new MergeOverlapAction()); 21 20 } -
applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyCombinePrimitiveResolverDialog.java
r30778 r30782 129 129 130 130 public void buildRelationCorrespondance(Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) { 131 getRelationMemberConflictResolverModel().buildRelationCorrespondance(targetPrimitive, newRelations, oldWays);131 getRelationMemberConflictResolverModel().buildRelationCorrespondance(targetPrimitive, newRelations, oldWays); 132 132 } 133 133 } -
applications/editors/josm/plugins/merge-overlap/src/mergeoverlap/hack/MyRelationMemberConflictResolverModel.java
r30766 r30782 53 53 @Override 54 54 public void populate(Collection<Relation> relations, Collection<? extends OsmPrimitive> memberPrimitives) { 55 throw new UnsupportedOperationException("Use populate(Collection<Relation>, Collection<? extends OsmPrimitive>, Map<Way, Way>) instead"); 55 throw new UnsupportedOperationException( 56 "Use populate(Collection<Relation>, Collection<? extends OsmPrimitive>, Map<Way, Way>) instead"); 56 57 } 57 58 … … 78 79 @Override 79 80 protected Command buildResolveCommand(Relation relation, OsmPrimitive newPrimitive) { 80 throw new UnsupportedOperationException("Use buildResolveCorrespondance(Relation, OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead"); 81 throw new UnsupportedOperationException( 82 "Use buildResolveCorrespondance(Relation, OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead"); 81 83 } 82 84 83 protected void buildResolveCorrespondance(Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) { 85 protected void buildResolveCorrespondance( 86 Relation relation, OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) { 84 87 85 List<RelationMember> relationsMembers = relation.getMembers();86 Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations);88 List<RelationMember> relationsMembers = relation.getMembers(); 89 Relation modifiedRelation = MergeOverlapAction.getNew(relation, newRelations); 87 90 modifiedRelation.setMembers(null); 88 91 for (int i=0; i < relationsMembers.size(); i++) { 89 RelationMember rm = relationsMembers.get(i);92 RelationMember rm = relationsMembers.get(i); 90 93 RelationMemberConflictDecision decision = getDecision(relation, i); 91 94 if (decision == null) { … … 94 97 switch(decision.getDecision()) { 95 98 case KEEP: 96 if (newPrimitive instanceof Way) {97 modifiedRelation.addMember(new RelationMember(decision.getRole(), MergeOverlapAction.getOld((Way)newPrimitive, oldWays)));98 }99 else {100 modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive));101 }99 if (newPrimitive instanceof Way) { 100 modifiedRelation.addMember(new RelationMember(decision.getRole(), 101 MergeOverlapAction.getOld((Way)newPrimitive, oldWays))); 102 } else { 103 modifiedRelation.addMember(new RelationMember(decision.getRole(), newPrimitive)); 104 } 102 105 break; 103 106 case REMOVE: … … 114 117 @Override 115 118 public List<Command> buildResolutionCommands(OsmPrimitive newPrimitive) { 116 throw new UnsupportedOperationException("Use buildRelationCorrespondance(OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead"); 119 throw new UnsupportedOperationException( 120 "Use buildRelationCorrespondance(OsmPrimitive, Map<Relation, Relation>, Map<Way, Way>) instead"); 117 121 } 118 122 … … 125 129 public void buildRelationCorrespondance(OsmPrimitive newPrimitive, Map<Relation, Relation> newRelations, Map<Way, Way> oldWays) { 126 130 for (Relation relation : relations) { 127 buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays);131 buildResolveCorrespondance(relation, newPrimitive, newRelations, oldWays); 128 132 } 129 133 }
Note:
See TracChangeset
for help on using the changeset viewer.
