Ticket #20041: 20041.patch
| File 20041.patch, 7.9 KB (added by , 5 years ago) |
|---|
-
src/org/openstreetmap/josm/actions/AlignInCircleAction.java
27 27 import org.openstreetmap.josm.data.osm.Node; 28 28 import org.openstreetmap.josm.data.osm.OsmPrimitive; 29 29 import org.openstreetmap.josm.data.osm.Way; 30 import org.openstreetmap.josm.data.osm.visitor.paint.relations.Multipolygon; 30 31 import org.openstreetmap.josm.gui.Notification; 31 32 import org.openstreetmap.josm.tools.Geometry; 32 33 import org.openstreetmap.josm.tools.Shortcut; … … 54 55 } 55 56 56 57 /** 57 * Create a {@link MoveCommand} to move a node to a PolarCoor.58 * Add a {@link MoveCommand} to move a node to a PolarCoor if there is a significant move. 58 59 * @param n Node to move 59 60 * @param coor polar coordinate where to move the node 60 * @ return new MoveCommand61 * @since 1310761 * @param cmds list of commands 62 * @since xxx 62 63 */ 63 public static MoveCommand createMoveCommand(Node n, PolarCoor coor) {64 public static void addMoveCommandIfNeeded(Node n, PolarCoor coor, List<Command> cmds) { 64 65 EastNorth en = coor.toEastNorth(); 65 return new MoveCommand(n, en.east() - n.getEastNorth().east(), en.north() - n.getEastNorth().north()); 66 double deltaEast = en.east() - n.getEastNorth().east(); 67 double deltaNorth = en.north() - n.getEastNorth().north(); 68 if (Math.abs(deltaEast) > 5e-6 || Math.abs(deltaNorth) > 5e-6) { 69 cmds.add(new MoveCommand(n, deltaEast, deltaNorth)); 70 } 66 71 } 67 72 68 73 /** … … 163 168 fixNodes.addAll(nodes); 164 169 // No need to reorder nodes since all are fix 165 170 } else { 166 // Invalid action 167 new Notification( 168 tr("Please select at least four nodes.")) 169 .setIcon(JOptionPane.INFORMATION_MESSAGE) 170 .setDuration(Notification.TIME_SHORT) 171 .show(); 171 showBadSelection(); 172 172 return; 173 173 } 174 174 175 if (!actionAllowed(nodes)) return; 176 175 177 if (center == null) { 176 178 // Compute the center of nodes 177 179 center = Geometry.getCenter(nodes); … … 194 196 radius = radius / nodes.size(); 195 197 } 196 198 197 if (!actionAllowed(nodes)) return;199 List<Command> cmds = new LinkedList<>(); 198 200 199 Collection<Command> cmds = new LinkedList<>();200 201 201 // Move each node to that distance from the center. 202 202 // Nodes that are not "fix" will be adjust making regular arcs. 203 203 int nodeCount = nodes.size(); … … 216 216 } 217 217 Node first = nodes.get(i % nodeCount); 218 218 PolarCoor pcFirst = new PolarCoor(radius, PolarCoor.computeAngle(first.getEastNorth(), center), center); 219 cmds.add(createMoveCommand(first, pcFirst));219 addMoveCommandIfNeeded(first, pcFirst, cmds); 220 220 if (j > i + 1) { 221 221 double delta; 222 222 if (j == i + nodeCount) { … … 230 230 } 231 231 for (int k = i+1; k < j; k++) { 232 232 PolarCoor p = new PolarCoor(radius, pcFirst.angle + (k-i)*delta, center); 233 cmds.add(createMoveCommand(nodes.get(k % nodeCount), p));233 addMoveCommandIfNeeded(nodes.get(k % nodeCount), p, cmds); 234 234 } 235 235 } 236 236 i = j; // Update start point for next iteration 237 237 } 238 if (cmds.isEmpty()) { 239 showBadSelection(); 240 } else { 241 UndoRedoHandler.getInstance().add(new SequenceCommand(tr("Align Nodes in Circle"), cmds)); 242 } 243 } 238 244 239 UndoRedoHandler.getInstance().add(new SequenceCommand(tr("Align Nodes in Circle"), cmds)); 245 private void showBadSelection() { 246 // Invalid action 247 new Notification( 248 tr("Selection could not be used to align in circle.")) 249 .setIcon(JOptionPane.INFORMATION_MESSAGE) 250 .setDuration(Notification.TIME_SHORT) 251 .show(); 240 252 } 241 253 242 254 /** … … 254 266 * @return Nodes anticlockwise ordered 255 267 */ 256 268 private static List<Node> collectNodesAnticlockwise(List<Way> ways) { 257 List<Node> nodes = new ArrayList<>(); 258 Node firstNode = ways.get(0).firstNode(); 259 Node lastNode = null; 260 Way lastWay = null; 261 while (firstNode != lastNode) { 262 if (lastNode == null) lastNode = firstNode; 263 for (Way way: ways) { 264 if (way == lastWay) continue; 265 if (way.firstNode() == lastNode) { 266 List<Node> wayNodes = way.getNodes(); 267 for (int i = 0; i < wayNodes.size() - 1; i++) { 268 nodes.add(wayNodes.get(i)); 269 } 270 lastNode = way.lastNode(); 271 lastWay = way; 272 break; 273 } 274 if (way.lastNode() == lastNode) { 275 List<Node> wayNodes = way.getNodes(); 276 for (int i = wayNodes.size() - 1; i > 0; i--) { 277 nodes.add(wayNodes.get(i)); 278 } 279 lastNode = way.firstNode(); 280 lastWay = way; 281 break; 282 } 283 } 284 } 285 // Check if nodes are in anticlockwise order 286 int nc = nodes.size(); 287 double area = 0; 288 for (int i = 0; i < nc; i++) { 289 EastNorth p1 = nodes.get(i).getEastNorth(); 290 EastNorth p2 = nodes.get((i+1) % nc).getEastNorth(); 291 area += p1.east()*p2.north() - p2.east()*p1.north(); 292 } 293 if (area < 0) 269 List<Node> nodes = new ArrayList<>(Multipolygon.joinWays(ways).iterator().next().getNodes()); 270 if (Geometry.isClockwise(nodes)) 294 271 Collections.reverse(nodes); 272 nodes.remove(nodes.size() - 1); 295 273 return nodes; 296 274 } 297 275 … … 323 301 } 324 302 325 303 /** 326 * Determines if ways can be joined into a polygon.304 * Determines if ways can be joined into a single polygon. 327 305 * @param ways The ways collection to check 328 * @return true if all ways can be joined into a polygon306 * @return true if all ways can be joined into a single polygon 329 307 */ 330 308 private static boolean checkWaysArePolygon(Collection<Way> ways) { 309 if (Multipolygon.joinWays(ways).size() != 1) 310 return false; 331 311 // For each way, nodes strictly between first and last should't be reference by an other way 332 312 for (Way way: ways) { 333 313 for (Node node: way.getNodes()) { … … 337 317 } 338 318 } 339 319 } 340 // Test if ways can be joined 341 Way currentWay = null; 342 Node startNode = null, endNode = null; 343 int used = 0; 344 while (true) { 345 Way nextWay = null; 346 for (Way w: ways) { 347 if (w.isClosed()) return ways.size() == 1; 348 if (w == currentWay) continue; 349 if (currentWay == null) { 350 nextWay = w; 351 startNode = w.firstNode(); 352 endNode = w.lastNode(); 353 break; 354 } 355 if (w.firstNode() == endNode) { 356 nextWay = w; 357 endNode = w.lastNode(); 358 break; 359 } 360 if (w.lastNode() == endNode) { 361 nextWay = w; 362 endNode = w.firstNode(); 363 break; 364 } 365 } 366 if (nextWay == null) return false; 367 used += 1; 368 currentWay = nextWay; 369 if (endNode == startNode) return used == ways.size(); 370 } 320 return true; 371 321 } 322 372 323 }
