Changeset 319 in josm for src/org/openstreetmap/josm/actions/ReorderAction.java
- Timestamp:
- 2007-09-04T10:21:49+02:00 (19 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
src/org/openstreetmap/josm/actions/ReorderAction.java
r301 r319 1 // License: GPL. Copyright 2007 by Immanuel Scholz and others1 //License: GPL. Copyright 2007 by Immanuel Scholz and others 2 2 package org.openstreetmap.josm.actions; 3 3 … … 10 10 import java.util.Iterator; 11 11 import java.util.LinkedList; 12 import java.util.HashMap; 12 13 13 14 import javax.swing.JOptionPane; … … 27 28 public ReorderAction() { 28 29 super(tr("Reorder Segments"), "reorder", tr("Try to reorder segments of a way so that they are in a line. May try to flip segments around to match a line."), KeyEvent.VK_R, KeyEvent.CTRL_DOWN_MASK | KeyEvent.ALT_DOWN_MASK, true); 29 }30 30 } 31 31 32 /** 32 33 * This method first sorts all the segments in a way, then makes sure that all … … 38 39 if (osm instanceof Way) 39 40 ways.add((Way)osm); 40 41 41 42 if (ways.size() < 1) { 42 43 JOptionPane.showMessageDialog(Main.parent, tr("Please select at least one way.")); 43 44 return; 44 45 } 45 46 46 47 if (ways.size() > 1) { 47 48 int answer = JOptionPane.showConfirmDialog(Main.parent, 48 trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()), 49 tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION); 49 trn(null, "You selected more than one way. Reorder the segments of {0} ways?", ways.size(), ways.size()), 50 tr("Reorder segments"), JOptionPane.OK_CANCEL_OPTION); 50 51 if (answer != JOptionPane.OK_OPTION) 51 52 return; … … 75 76 * the segments are facing the same direction as the first one. 76 77 * @param way The way to reorder 77 * @return The command needed to reorder the way78 */79 public static Command reorderWay(Way way) {80 final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false));81 82 Collection<Command> c = new LinkedList<Command>();83 84 boolean direction = false;85 // work out the "average" direction of the way, we use this to direct the rest of the segments86 int dirCounter = 0;87 for(int i = 0; i < sel.size() - 1; i++)88 {89 Segment firstSegment = sel.get(i);90 Segment secondSegment = sel.get(i+1);91 if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way92 dirCounter++;93 else94 dirCounter--;95 }96 if ( dirCounter <= 0 )97 direction = false;98 else99 direction = true;100 101 Node lastNode = null;102 103 // we need to calculate what the first node in the way is, we work from there104 Segment firstSegment = sel.getFirst();105 Segment secondSegment = sel.get(1);106 if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to)107 lastNode = firstSegment.from;108 else109 lastNode = firstSegment.to;110 111 // go through each segment and flip them if required112 for (Segment s : sel) {113 Segment snew = new Segment(s);114 boolean segDirection = s.from == lastNode;115 // segDirection = true when the 'from' node occurs before the 'to' node in the Way116 if (direction != segDirection)117 {118 // reverse the segment's direction119 Node n = snew.from;120 snew.from = snew.to;121 snew.to = n;122 c.add(new ChangeCommand(s, snew));123 }124 125 if (direction) // if its facing forwards,126 lastNode = snew.to; // our next node is the 'to' one127 else128 lastNode = snew.from; // otherwise its the 'from' one129 }130 131 LinkedList<Segment> segments = new LinkedList<Segment>();132 133 // Now we recreate the segment list, in the correct order of the direction134 for (Segment s : sel)135 if (!direction)136 segments.addFirst(s);137 else138 segments.addLast(s);139 140 // Check if the new segment list is actually different from the old one141 // before we go and add a change command for it142 for(int i = 0; i < segments.size(); i++)143 if (way.segments.get(i) != segments.get(i))144 {145 Way newWay = new Way(way);146 newWay.segments.clear();147 newWay.segments.addAll(segments);148 c.add(new ChangeCommand(way, newWay));149 break;150 }151 152 // Check we've got some change commands before we add a sequence command78 * @return The command needed to reorder the way 79 */ 80 public static Command reorderWay(Way way) { 81 final LinkedList<Segment> sel = new LinkedList<Segment>(sortSegments(new LinkedList<Segment>(way.segments), false)); 82 83 Collection<Command> c = new LinkedList<Command>(); 84 85 boolean direction = false; 86 // work out the "average" direction of the way, we use this to direct the rest of the segments 87 int dirCounter = 0; 88 for(int i = 0; i < sel.size() - 1; i++) 89 { 90 Segment firstSegment = sel.get(i); 91 Segment secondSegment = sel.get(i+1); 92 if ( firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to ) // direction = true when 'from' is the first node in the Way 93 dirCounter++; 94 else 95 dirCounter--; 96 } 97 if ( dirCounter <= 0 ) 98 direction = false; 99 else 100 direction = true; 101 102 Node lastNode = null; 103 104 // we need to calculate what the first node in the way is, we work from there 105 Segment firstSegment = sel.getFirst(); 106 Segment secondSegment = sel.get(1); 107 if (firstSegment.to == secondSegment.from || firstSegment.to == secondSegment.to) 108 lastNode = firstSegment.from; 109 else 110 lastNode = firstSegment.to; 111 112 // go through each segment and flip them if required 113 for (Segment s : sel) { 114 Segment snew = new Segment(s); 115 boolean segDirection = s.from == lastNode; 116 // segDirection = true when the 'from' node occurs before the 'to' node in the Way 117 if (direction != segDirection) 118 { 119 // reverse the segment's direction 120 Node n = snew.from; 121 snew.from = snew.to; 122 snew.to = n; 123 c.add(new ChangeCommand(s, snew)); 124 } 125 126 if (direction) // if its facing forwards, 127 lastNode = snew.to; // our next node is the 'to' one 128 else 129 lastNode = snew.from; // otherwise its the 'from' one 130 } 131 132 LinkedList<Segment> segments = new LinkedList<Segment>(); 133 134 // Now we recreate the segment list, in the correct order of the direction 135 for (Segment s : sel) 136 if (!direction) 137 segments.addFirst(s); 138 else 139 segments.addLast(s); 140 141 // Check if the new segment list is actually different from the old one 142 // before we go and add a change command for it 143 for(int i = 0; i < segments.size(); i++) 144 if (way.segments.get(i) != segments.get(i)) 145 { 146 Way newWay = new Way(way); 147 newWay.segments.clear(); 148 newWay.segments.addAll(segments); 149 c.add(new ChangeCommand(way, newWay)); 150 break; 151 } 152 153 // Check we've got some change commands before we add a sequence command 153 154 if (c.size() != 0) { 154 155 NameVisitor v = new NameVisitor(); … … 157 158 } 158 159 return null; 159 }160 } 160 161 161 162 /** … … 168 169 */ 169 170 public static LinkedList<Segment> sortSegments(LinkedList<Segment> segments, boolean strict) { 170 171 171 172 LinkedList<Segment> sortedSegments = new LinkedList<Segment>(); 172 173 173 174 while (!segments.isEmpty()) { 174 175 LinkedList<Segment> pivotList = new LinkedList<Segment>(); 175 pivotList.add(segments .getFirst());176 segments.remove First();176 pivotList.add(firstSegment(segments)); 177 segments.remove(pivotList.getLast()); 177 178 boolean found; 178 179 do { 179 180 found = false; 181 //try working forwards first 180 182 for (Iterator<Segment> it = segments.iterator(); it.hasNext();) { 181 183 Segment ls = it.next(); 182 184 if (ls.incomplete) 183 185 continue; // incomplete segments are never added to a new way 184 if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) {186 if (ls.from == pivotList.getLast().to) { 185 187 pivotList.addLast(ls); 186 188 it.remove(); 187 189 found = true; 188 } else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) { 189 pivotList.addFirst(ls); 190 it.remove(); 191 found = true; 190 } 191 } 192 if(!found){ 193 for (Iterator<Segment> it = segments.iterator(); it.hasNext();) { 194 Segment ls = it.next(); 195 if (ls.incomplete) 196 continue; // incomplete segments are never added to a new way 197 if (ls.from == pivotList.getLast().to || (!strict && (ls.to == pivotList.getLast().to || ls.from == pivotList.getLast().from || ls.to == pivotList.getLast().from))) { 198 pivotList.addLast(ls); 199 it.remove(); 200 found = true; 201 } else if (ls.to == pivotList.getFirst().from || (!strict && (ls.from == pivotList.getFirst().from || ls.to == pivotList.getFirst().to || ls.from == pivotList.getFirst().to))) { 202 pivotList.addFirst(ls); 203 it.remove(); 204 found = true; 205 } 192 206 } 193 207 } … … 195 209 sortedSegments.addAll(pivotList); 196 210 } 197 return sortedSegments; 198 } 211 return sortedSegments; 212 } 213 214 /** 215 * This method searches for a good segment to start a reorder from. 216 * In most cases this will be a segment with a start node that occurs only 217 * once in the way. In cases with loops, this could be any odd number. If no nodes 218 * are referenced an odd number of times, then any segment is a good start point. 219 */ 220 public static Segment firstSegment(Collection<Segment> segments) { 221 HashMap<Node, Integer> refCount = new HashMap<Node, Integer>(segments.size()*2); 222 //loop through all segments and count up how many times each node is referenced 223 for (Segment seg : segments) { 224 if (!refCount.containsKey(seg.from)) 225 refCount.put(seg.from, 0); 226 refCount.put(seg.from,refCount.get(seg.from)+1); 227 228 if (!refCount.containsKey(seg.to)) 229 refCount.put(seg.to, 0); 230 refCount.put(seg.to,refCount.get(seg.to)+1); 231 } 232 233 //now look for start nodes that are referenced only once 234 for (Segment seg : segments) 235 if (refCount.get(seg.from) == 1) 236 return seg; 237 //now look for start nodes that are referenced only (2n+1) 238 for (Segment seg : segments) 239 if (refCount.get(seg.from) % 2 == 1) 240 return seg; 241 //now look for end nodes that are referenced only once 242 for (Segment seg : segments) 243 if (refCount.get(seg.to) == 1) 244 return seg; 245 //now look for end nodes that are referenced only (2n+1) 246 for (Segment seg : segments) 247 if (refCount.get(seg.to) % 2 == 1) 248 return seg; 249 250 return segments.iterator().next(); 251 } 199 252 }
Note:
See TracChangeset
for help on using the changeset viewer.
