Changeset 26844 in osm for applications/editors/josm/plugins/reltoolbox/src/relcontext
- Timestamp:
- 2011-10-12T23:23:14+02:00 (13 years ago)
- Location:
- applications/editors/josm/plugins/reltoolbox/src/relcontext/actions
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/SplittingMultipolygons.java
r26837 r26844 55 55 56 56 public static List<Relation> process( Collection<Way> selectedWays, List<Command> commands ) { 57 System.out.println("---------------------------------------"); 57 58 List<Relation> result = new ArrayList<Relation>(); 58 59 List<Way> rings = new ArrayList<Way>(); … … 279 280 280 281 /** 281 * Find a way the tips of a segment, ensure it's in a multipolygon and try to close the relation.282 */ 283 public static Relation attachRingToNeighbours( Way segment, List<Command> resultingCommands ) {284 if( ! segment.isClosed() || segment.isIncomplete() )282 * Make a multipolygon out of the ring, but split it to attach to neighboring multipolygons. 283 */ 284 public static Relation attachRingToNeighbours( Way ring, List<Command> resultingCommands ) { 285 if( !ring.isClosed() || ring.isIncomplete() ) 285 286 return null; 286 287 return null; // todo 287 Map<Way, Boolean> touchingWays = new HashMap<Way, Boolean>(); 288 for( Node n : ring.getNodes() ) { 289 for( OsmPrimitive p : n.getReferrers() ) { 290 if( p instanceof Way && !p.equals(ring) ) { 291 for( OsmPrimitive r : p.getReferrers() ) { 292 if( r instanceof Relation && ((Relation)r).hasKey("type") && ((Relation)r).get("type").equals("multipolygon") ) { 293 if( touchingWays.containsKey((Way)p) ) 294 touchingWays.put((Way)p, Boolean.TRUE); 295 else 296 touchingWays.put((Way)p, Boolean.FALSE); 297 break; 298 } 299 } 300 } 301 } 302 } 303 304 List<TheRing> otherWays = new ArrayList<TheRing>(); 305 for( Way w : touchingWays.keySet() ) 306 if( touchingWays.get(w) ) { 307 otherWays.add(new TheRing(w)); 308 System.out.println("Touching ring: " + otherWays.get(otherWays.size()-1)); 309 } 310 311 // for( Iterator<Way> keys = touchingWays.keySet().iterator(); keys.hasNext(); ) { 312 // if( !touchingWays.get(keys.next()) ) 313 // keys.remove(); 314 // } 315 316 // now touchingWays has only ways that touch the ring twice 317 List<Command> commands = new ArrayList<Command>(); 318 TheRing theRing = new TheRing(ring); // this is actually useful 319 320 for( TheRing otherRing : otherWays ) 321 theRing.collide(otherRing); 322 323 theRing.putSourceWayFirst(); 324 for( TheRing otherRing : otherWays ) 325 otherRing.putSourceWayFirst(); 326 327 for( TheRing otherRing : otherWays ) 328 commands.addAll(otherRing.getCommands(false)); 329 commands.addAll(theRing.getCommands()); 330 resultingCommands.add(new SequenceCommand(tr("Complete multipolygon for way {0}", 331 DefaultNameFormatter.getInstance().format(ring)), commands)); 332 return theRing.getRelation(); 288 333 } 289 334 } -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/TheRing.java
r26837 r26844 81 81 RingSegment segment2 = other.segments.get(j); 82 82 if( !segment2.isReference() ) { 83 List<Node> nodes1 = segment1.getNodes(); 84 List<Node> nodes2 = segment2.getNodes(); 85 boolean isRing1 = segment1.isRing(); 86 boolean isRing2 = segment2.isRing(); 87 88 int pos = 0; 89 while( pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) 90 pos++; 91 boolean collideFound = pos == nodes1.size(); 92 if( pos == 0 && isRing1 ) { 93 // rewind a bit 94 pos = nodes1.size() - 1; 95 while( pos > 0 && nodes2.contains(nodes1.get(pos)) ) pos--; 96 if( pos == 0 ) { 97 JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE); 98 return; 83 System.out.println("Comparing " + segment1 + " and " + segment2); 84 Node[] split = getSplitNodes(segment1.getNodes(), segment2.getNodes(), segment1.isRing(), segment2.isRing()); 85 if( split != null ) { 86 if( !collideNoted ) { 87 System.out.println("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 88 collideNoted = true; 99 89 } 100 pos = pos == nodes1.size() ? 0 : pos + 1; 101 } 102 System.out.println("Comparing " + segment1 + " and " + segment2); 103 int firstPos = isRing1 ? pos : nodes1.size(); 104 while( !collideFound ) { 105 System.out.println("pos="+pos); 106 int start1 = pos; 107 int start2 = nodes2.indexOf(nodes1.get(start1)); 108 int last1 = incrementBy(start1, 1, nodes1.size(), isRing1); 109 int last2 = start2; 110 int increment2 = 0; 111 if( last1 >= 0 ) { 112 last2 = incrementBy(start2, -1, nodes2.size(), isRing2); 113 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 114 increment2 = -1; 115 else { 116 last2 = incrementBy(start2, 1, nodes2.size(), isRing2); 117 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 118 increment2 = 1; 119 } 120 } 121 System.out.println("last1="+last1+" last2="+last2+" increment2="+increment2); 122 if( increment2 != 0 ) { 123 if( !collideNoted ) { 124 System.out.println("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 125 collideNoted = true; 126 } 127 // find the first nodes 128 boolean reachedEnd = false; 129 while( !reachedEnd ) { 130 int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1); 131 int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2); 132 if( newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) 133 reachedEnd = true; 134 else { 135 last1 = newLast1; 136 last2 = newLast2; 137 } 138 } 139 System.out.println("last1=" + last1 + " last2=" + last2); 140 if( increment2 < 0 ) { 141 int tmp = start2; 142 start2 = last2; 143 last2 = tmp; 144 } 145 RingSegment segment = splitRingAt(i, nodes1.get(start1), nodes1.get(last1)); 146 RingSegment otherSegment = other.splitRingAt(j, nodes2.get(start2), nodes2.get(last2)); 147 if( !areSegmentsEqual(segment, otherSegment) ) 148 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment); 149 segment.makeReference(otherSegment); 150 collideFound = true; 151 } else { 152 pos = last1; 153 while( pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) 154 pos = incrementBy(pos, 1, nodes1.size(), isRing1); 155 if( pos < 0 || !nodes2.contains(nodes1.get(pos)) ) 156 collideFound = true; 157 } 90 RingSegment segment = splitRingAt(i, split[0], split[1]); 91 RingSegment otherSegment = other.splitRingAt(j, split[2], split[3]); 92 if( !areSegmentsEqual(segment, otherSegment) ) 93 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment); 94 segment.makeReference(otherSegment); 158 95 } 159 96 } … … 165 102 } 166 103 167 private int incrementBy( int value, int increment, int limit1, boolean isRing ) { 104 /** 105 * Returns array of {start1, last1, start2, last2} or null if there is no common nodes. 106 */ 107 public static Node[] getSplitNodes( List<Node> nodes1, List<Node> nodes2, boolean isRing1, boolean isRing2 ) { 108 int pos = 0; 109 while( pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) 110 pos++; 111 boolean collideFound = pos == nodes1.size(); 112 if( pos == 0 && isRing1 ) { 113 // rewind a bit 114 pos = nodes1.size() - 1; 115 while( pos > 0 && nodes2.contains(nodes1.get(pos)) ) 116 pos--; 117 if( pos == 0 ) { 118 JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE); 119 return null; 120 } 121 pos = pos == nodes1.size() - 1 ? 0 : pos + 1; 122 } 123 int firstPos = isRing1 ? pos : nodes1.size(); 124 while( !collideFound ) { 125 System.out.println("pos=" + pos); 126 int start1 = pos; 127 int start2 = nodes2.indexOf(nodes1.get(start1)); 128 int last1 = incrementBy(start1, 1, nodes1.size(), isRing1); 129 int last2 = start2; 130 int increment2 = 0; 131 if( last1 >= 0 ) { 132 last2 = incrementBy(start2, -1, nodes2.size(), isRing2); 133 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 134 increment2 = -1; 135 else { 136 last2 = incrementBy(start2, 1, nodes2.size(), isRing2); 137 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 138 increment2 = 1; 139 } 140 } 141 System.out.println("last1=" + last1 + " last2=" + last2 + " increment2=" + increment2); 142 if( increment2 != 0 ) { 143 // find the first nodes 144 boolean reachedEnd = false; 145 while( !reachedEnd ) { 146 int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1); 147 int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2); 148 if( newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) 149 reachedEnd = true; 150 else { 151 last1 = newLast1; 152 last2 = newLast2; 153 } 154 } 155 System.out.println("last1=" + last1 + " last2=" + last2); 156 if( increment2 < 0 ) { 157 int tmp = start2; 158 start2 = last2; 159 last2 = tmp; 160 } 161 return new Node[] {nodes1.get(start1), nodes1.get(last1), nodes2.get(start2), nodes2.get(last2)}; 162 } else { 163 pos = last1; 164 while( pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) 165 pos = incrementBy(pos, 1, nodes1.size(), isRing1); 166 if( pos < 0 || pos == firstPos || !nodes2.contains(nodes1.get(pos)) ) 167 collideFound = true; 168 } 169 } 170 return null; 171 } 172 173 private static int incrementBy( int value, int increment, int limit1, boolean isRing ) { 168 174 int result = value + increment; 169 175 if( result < 0 ) … … 216 222 if( thirdPart != null ) 217 223 segments.add(pos++, thirdPart); 218 RingSegment result = isRing || secondPart == null ? segment : secondPart; 219 // System.out.println("Returning segment " + result); 220 return result; 224 return isRing || secondPart == null ? segment : secondPart; 221 225 } 222 226 … … 225 229 * Also, sets source way for all rings. 226 230 * 227 * This method should be called, even if there is just one ring.231 * If this method is not called, do not forget to call {@link #putSourceWayFirst()} for all rings. 228 232 */ 229 233 public static void redistributeSegments( List<TheRing> rings ) { … … 263 267 } 264 268 265 p rivatevoid putSourceWayFirst() {269 public void putSourceWayFirst() { 266 270 for( RingSegment seg : segments ) { 267 271 if( !seg.isReference() ) { … … 271 275 } 272 276 } 273 277 278 public List<Command> getCommands() { 279 return getCommands(true); 280 } 281 274 282 /** 275 283 * Returns a list of commands to make a new relation and all newly created ways. 276 284 * The first way is copied from the source one, ChangeCommand is issued in this case. 277 285 */ 278 public List<Command> getCommands() { 279 System.out.println("Making ring " + this); 280 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 281 relation = new Relation(); 282 relation.put("type", "multipolygon"); 286 public List<Command> getCommands( boolean createMultipolygon ) { 283 287 Way sourceCopy = new Way(source); 284 for( String key : sourceCopy.keySet() ) { 285 if( !linearTags.contains(key) ) { 286 relation.put(key, sourceCopy.get(key)); 287 sourceCopy.remove(key); 288 if( createMultipolygon ) { 289 Collection<String> linearTags = Main.pref.getCollection(PREF_MULTIPOLY + "lineartags", CreateMultipolygonAction.DEFAULT_LINEAR_TAGS); 290 relation = new Relation(); 291 relation.put("type", "multipolygon"); 292 for( String key : sourceCopy.keySet() ) { 293 if( !linearTags.contains(key) ) { 294 relation.put(key, sourceCopy.get(key)); 295 sourceCopy.remove(key); 296 } 288 297 } 289 298 } … … 310 319 commands.add(new AddCommand(w)); 311 320 if( w.equals(source) ) { 312 if( segments.size() == 1 ) { 313 // one segment means that it is a ring 314 List<Node> segnodes = seg.getNodes(); 315 segnodes.add(segnodes.get(0)); 316 sourceCopy.setNodes(segnodes); 317 } else 318 sourceCopy.setNodes(seg.getNodes()); 319 commands.add(new ChangeCommand(source, sourceCopy)); 321 if( createMultipolygon || !seg.getWayNodes().equals(source.getNodes()) ) { 322 sourceCopy.setNodes(seg.getWayNodes()); 323 commands.add(new ChangeCommand(source, sourceCopy)); 324 } 320 325 foundOwnWay = true; 321 326 } else { … … 325 330 } 326 331 } 327 relation.addMember(new RelationMember("outer", w)); 332 if( createMultipolygon ) 333 relation.addMember(new RelationMember("outer", w)); 328 334 } 329 335 if( !foundOwnWay ) 330 336 commands.add(new DeleteCommand(source)); 331 337 commands.addAll(relationCommands); 332 commands.add(new AddCommand(relation)); 338 if( createMultipolygon ) 339 commands.add(new AddCommand(relation)); 333 340 return commands; 334 341 } … … 463 470 } 464 471 472 public List<Node> getWayNodes() { 473 if( nodes == null ) 474 throw new IllegalArgumentException("Won't give you wayNodes: it is a reference"); 475 List<Node> wayNodes = new ArrayList<Node>(nodes); 476 if( isRing ) 477 wayNodes.add(wayNodes.get(0)); 478 return wayNodes; 479 } 480 465 481 public boolean isReference() { 466 482 return nodes == null; … … 493 509 if( resultingWay == null ) { 494 510 resultingWay = new Way(); 495 resultingWay.setNodes( nodes);511 resultingWay.setNodes(getWayNodes()); 496 512 } 497 513 if( template != null && !wasTemplateApplied ) {
Note:
See TracChangeset
for help on using the changeset viewer.