Changeset 26834 in osm for applications/editors/josm/plugins/reltoolbox/src/relcontext
- Timestamp:
- 2011-10-11T22:52:35+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/CreateMultipolygonAction.java
r26816 r26834 408 408 private boolean areAllOfThoseRings( Collection<Way> ways ) { 409 409 List<Way> rings = new ArrayList<Way>(); 410 List<Way> otherWays = new ArrayList<Way>();411 410 for( Way way : ways ) { 412 411 if( way.isClosed() ) 413 412 rings.add(way); 414 413 else 415 otherWays.add(way);414 return false; 416 415 } 417 416 if( rings.isEmpty() || ways.size() == 1 ) 418 417 return false; // todo: for one ring, attach it to neares multipolygons 419 420 // check that every segment touches just one ring421 for( Way segment : otherWays ) {422 boolean found = false;423 for( Way ring : rings ) {424 if( ring.containsNode(segment.firstNode()) && ring.containsNode(segment.lastNode())425 && !segmentInsidePolygon(segment.getNode(0), segment.getNode(1), ring.getNodes()) )426 found = true;427 }428 if( !found )429 return false;430 }431 418 432 419 // check for non-containment of rings -
applications/editors/josm/plugins/reltoolbox/src/relcontext/actions/TheRing.java
r26832 r26834 2 2 3 3 import java.util.*; 4 import javax.swing.JOptionPane; 4 5 import org.openstreetmap.josm.Main; 5 6 import org.openstreetmap.josm.command.*; … … 30 31 boolean collideNoted = false; 31 32 for( int i = 0; i < segments.size(); i++ ) { 32 if( !segments.get(i).isReference() ) { 33 RingSegment segment1 = segments.get(i); 34 if( !segment1.isReference() ) { 33 35 for( int j = 0; j < other.segments.size(); j++ ) { 34 if( !other.segments.get(j).isReference() ) { 35 RingSegment seg1 = segments.get(i); 36 RingSegment seg2 = other.segments.get(j); 37 boolean firstSegmentIsNotARing = !seg1.isRing() && segments.size() == 1; 38 if( !seg2.isRing() && other.segments.size() == 1 ) { 39 if( firstSegmentIsNotARing ) 40 break; // not doing two arcs collision 41 RingSegment tmp = seg1; 42 seg1 = seg2; 43 seg2 = tmp; 44 firstSegmentIsNotARing = true; 36 RingSegment segment2 = other.segments.get(j); 37 if( !segment2.isReference() ) { 38 List<Node> nodes1 = segment1.getNodes(); 39 List<Node> nodes2 = segment2.getNodes(); 40 boolean isRing1 = segment1.isRing(); 41 boolean isRing2 = segment2.isRing(); 42 43 int pos = 0; 44 while( pos < nodes1.size() && !nodes2.contains(nodes1.get(pos)) ) 45 pos++; 46 boolean collideFound = pos == nodes1.size(); 47 if( pos == 0 && isRing1 ) { 48 // rewind a bit 49 pos = nodes1.size() - 1; 50 while( pos > 0 && nodes2.contains(nodes1.get(pos)) ) pos--; 51 if( pos == 0 ) { 52 JOptionPane.showMessageDialog(Main.parent, "Two rings are equal, and this must not be.", "Multipolygon from rings", JOptionPane.ERROR_MESSAGE); 53 return; 54 } 55 pos = pos == nodes1.size() ? 0 : pos + 1; 45 56 } 46 if( firstSegmentIsNotARing ) { 47 if( seg2.getNodes().contains(seg1.getNodes().get(0)) && seg2.getNodes().contains(seg1.getNodes().get(seg1.getNodes().size()-2))) { 48 // segment touches a ring 49 57 System.out.println("Comparing " + segment1 + " and " + segment2); 58 int firstPos = isRing1 ? pos : nodes1.size(); 59 while( !collideFound ) { 60 System.out.println("pos="+pos); 61 int start1 = pos; 62 int start2 = nodes2.indexOf(nodes1.get(start1)); 63 int last1 = incrementBy(start1, 1, nodes1.size(), isRing1); 64 int last2 = start2; 65 int increment2 = 0; 66 if( last1 >= 0 ) { 67 last2 = incrementBy(start2, -1, nodes2.size(), isRing2); 68 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 69 increment2 = -1; 70 else { 71 last2 = incrementBy(start2, 1, nodes2.size(), isRing2); 72 if( last2 >= 0 && nodes1.get(last1).equals(nodes2.get(last2)) ) 73 increment2 = 1; 74 } 50 75 } 51 } else { 52 // both are segments from rings, find intersection 53 } 54 55 56 Node[] intersection = getFirstIntersection(segments.get(i), other.segments.get(j)); 57 if( intersection.length > 1 ) { 58 if( !collideNoted ) { 59 System.out.println("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 60 collideNoted = true; 61 } 62 // now split both ways at control points and remove duplicate parts 63 boolean[] isarc = new boolean[] { 64 segments.size() == 1 && !segments.get(0).isRing(), 65 other.segments.size() == 1 && !other.segments.get(0).isRing() 66 }; 67 RingSegment segment = splitRingAt(i, intersection[0], intersection[1]); 68 RingSegment otherSegment = other.splitRingAt(j, intersection[0], intersection[1]); 69 if( !isarc[0] && !isarc[1] ) { 70 if( segments.size() > 2 && other.segments.size() > 2 ) 71 segment.makeReference(otherSegment); 72 else { 73 System.out.println("Starting complex procedure. Rings: " + this + " and " + other); 74 // this ring was a ring, and we're not sure "segment" is a correct segment 75 // actually, we're not sure always 76 if( segments.size() == 2 ) 77 segment = segments.get(0); 78 if( other.segments.size() == 2 ) 79 otherSegment = other.segments.get(0); 80 System.out.println("segment="+segment + ", otherSegment=" + otherSegment); 81 82 if( areSegmentsEqual(segment, otherSegment) ) 83 segment.makeReference(otherSegment); 84 else if( segments.size() == 2 && areSegmentsEqual(segments.get(1), otherSegment) ) 85 segments.get(1).makeReference(otherSegment); 86 else if( areSegmentsEqual(segment, other.segments.get(1)) ) 87 segment.makeReference(other.segments.get(1)); 88 else 89 segments.get(1).makeReference(other.segments.get(1)); 76 System.out.println("last1="+last1+" last2="+last2+" increment2="+increment2); 77 if( increment2 != 0 ) { 78 if( !collideNoted ) { 79 System.out.println("Rings for ways " + source.getUniqueId() + " and " + other.source.getUniqueId() + " collide."); 80 collideNoted = true; 90 81 } 91 } else {92 // 1. A ring is an arc. It should have only 2 segments after this93 // 2. But it has one, so add otherSegment as the second.94 // 3. determine which segment!95 if( isarc[0] ) {96 if( other.segments.size() > 2)97 segments.add(new RingSegment(otherSegment));82 // find the first nodes 83 boolean reachedEnd = false; 84 while( !reachedEnd ) { 85 int newLast1 = incrementBy(last1, 1, nodes1.size(), isRing1); 86 int newLast2 = incrementBy(last2, increment2, nodes2.size(), isRing2); 87 if( newLast1 < 0 || newLast2 < 0 || !nodes1.get(newLast1).equals(nodes2.get(newLast2)) ) 88 reachedEnd = true; 98 89 else { 99 // choose between 2 segments 100 int segmentToAdd = whichSegmentIsCloser(segments.get(0), other.segments.get(0), other.segments.get(1)); 101 segments.add(new RingSegment(other.segments.get(segmentToAdd))); 102 } 103 } else { 104 if( segments.size() > 2 ) 105 other.segments.add(new RingSegment(segment)); 106 else { 107 // choose between 2 segments 108 int segmentToAdd = whichSegmentIsCloser(other.segments.get(0), segments.get(0), segments.get(1)); 109 other.segments.add(new RingSegment(segments.get(segmentToAdd))); 90 last1 = newLast1; 91 last2 = newLast2; 110 92 } 111 93 } 94 System.out.println("last1=" + last1 + " last2=" + last2); 95 if( increment2 < 0 ) { 96 int tmp = start2; 97 start2 = last2; 98 last2 = tmp; 99 } 100 RingSegment segment = splitRingAt(i, nodes1.get(start1), nodes1.get(last1)); 101 RingSegment otherSegment = other.splitRingAt(j, nodes2.get(start2), nodes2.get(last2)); 102 if( !areSegmentsEqual(segment, otherSegment) ) 103 throw new IllegalArgumentException("Error: algorithm gave incorrect segments: " + segment + " and " + otherSegment); 104 segment.makeReference(otherSegment); 105 collideFound = true; 106 } else { 107 pos = last1; 108 while( pos != firstPos && pos >= 0 && !nodes2.contains(nodes1.get(pos)) ) 109 pos = incrementBy(pos, 1, nodes1.size(), isRing1); 110 if( pos < 0 || !nodes2.contains(nodes1.get(pos)) ) 111 collideFound = true; 112 112 } 113 113 } 114 114 } 115 if( segment s.get(i).isReference() )115 if( segment1.isReference() ) 116 116 break; 117 117 } … … 120 120 } 121 121 122 private Node[] getFirstIntersection( RingSegment seg1, RingSegment seg2 ) { 123 List<Node> intersectionNodes = new ArrayList<Node>(); 124 boolean colliding = false; 125 List<Node> nodes1 = seg1.getNodes(); 126 List<Node> nodes2 = seg2.getNodes(); 127 for( int ni = 0; ni < nodes2.size(); ni++ ) { 128 if( nodes1.contains(nodes2.get(ni)) != colliding ) { 129 intersectionNodes.add(nodes2.get(colliding ? ni - 1 : ni)); 130 colliding = !colliding; 131 } 132 } 133 if( colliding ) 134 intersectionNodes.add(nodes2.get(nodes2.size() - 1)); 135 // when an intersection of two rings spans a ring's beginning 136 if( seg1.isRing() && seg2.isRing() && intersectionNodes.contains(nodes2.get(0)) && intersectionNodes.contains(nodes2.get(nodes2.size() - 1)) ) { 137 intersectionNodes.remove(0); 138 intersectionNodes.remove(intersectionNodes.size() - 1); 139 intersectionNodes.add(intersectionNodes.get(0)); 140 intersectionNodes.remove(0); 141 } 142 System.out.print("Intersection nodes for segments " + seg1 + " and " + seg2 + ": "); 143 for( Node inode : intersectionNodes ) 144 System.out.print(inode.getUniqueId() + ","); 145 System.out.println(); 146 // unclosed ways produce duplicate nodes 147 int ni = 1; 148 while( ni < intersectionNodes.size() ) { 149 if( intersectionNodes.get(ni - 1).equals(intersectionNodes.get(ni)) ) 150 intersectionNodes.remove(ni - 1); 151 else 152 ni++; 153 } 154 return intersectionNodes.toArray(new Node[2]); 155 } 156 157 private int whichSegmentIsCloser( RingSegment base, RingSegment test0, RingSegment test1 ) { 158 List<Node> testRing = new ArrayList<Node>(base.getNodes()); 159 closePolygon(testRing, test1.getNodes()); 160 return segmentInsidePolygon(test1.getNodes().get(0), test1.getNodes().get(1), testRing) ? 1 : 0; 122 private int incrementBy( int value, int increment, int limit1, boolean isRing ) { 123 int result = value + increment; 124 if( result < 0 ) 125 return isRing ? result + limit1 : -1; 126 else if( result >= limit1 ) 127 return isRing ? result - limit1 : -1; 128 else 129 return result; 161 130 } 162 131 … … 364 333 } 365 334 366 /**367 * Copies segment from {@code ring} to close a multipolygon containing {@code segment}.368 * @param segment Unclosed segment.369 * @param ring Closed ring.370 * @return Missing way.371 */372 private Way makeIntersectionLine( Way segment, Way ring ) {373 List<Node> nodes = new ArrayList<Node>(ring.getNodes());374 nodes.remove(nodes.size() - 1);375 int index1 = nodes.indexOf(segment.firstNode());376 int index2 = nodes.indexOf(segment.lastNode());377 if( index1 == index2 || index1 < 0 || index2 < 0 )378 return null;379 380 // split ring381 List<List<Node>> chunks = new ArrayList<List<Node>>(2);382 chunks.add(new ArrayList<Node>());383 chunks.add(new ArrayList<Node>());384 int chunk = 0, i = index1;385 boolean madeCircle = false;386 while( i != index1 || !madeCircle ) {387 chunks.get(chunk).add(nodes.get(i));388 if( i == index2 ) {389 chunk = 1 - chunk;390 chunks.get(chunk).add(nodes.get(i));391 }392 if( ++i >= nodes.size() )393 i = 0;394 madeCircle = true;395 }396 chunks.get(chunk).add(nodes.get(i));397 398 // check which segment to add399 List<Node> testRing = new ArrayList<Node>(segment.getNodes());400 closePolygon(testRing, chunks.get(0));401 chunk = segmentInsidePolygon(chunks.get(1).get(0), chunks.get(1).get(1), testRing) ? 1 : 0;402 403 // create way404 Way w = new Way();405 w.setKeys(segment.getKeys());406 w.setNodes(chunks.get(chunk));407 return w;408 }409 410 335 private static class RingSegment { 411 336 private List<Node> nodes;
Note:
See TracChangeset
for help on using the changeset viewer.