Changeset 6892 in josm
 Timestamp:
 20140302T11:37:47+01:00 (7 years ago)
 File:

 1 edited
Legend:
 Unmodified
 Added
 Removed

trunk/src/org/openstreetmap/josm/actions/AlignInCircleAction.java
r6814 r6892 89 89 + origin.north()); 90 90 } 91 92 /** 93 * Create a MoveCommand to move a node to this PolarCoor. 94 * @param n Node to move 95 * @return new MoveCommand 96 */ 97 public MoveCommand createMoveCommand(Node n) { 98 EastNorth en = toEastNorth(); 99 return new MoveCommand(n, en.east()  n.getEastNorth().east(), en.north()  n.getEastNorth().north()); 100 } 91 101 } 92 102 … … 113 123 // special case if no single nodes are selected and exactly one way is: 114 124 // then use the way's nodes 115 if ((nodes.size() <= 2) && (ways.size() == 1)) { 116 Way way = ways.get(0); 117 125 if ((nodes.size() <= 2) && checkWaysArePolygon(ways)) { 118 126 // some more special combinations: 119 127 // When is selected node that is part of the way, then make a regular polygon, selected … … 124 132 // When one more node, part of the way, is selected, set the radius equal to the 125 133 // distance between two nodes. 126 if (nodes.size() > 0) { 127 if (nodes.size() == 1 && way.containsNode(nodes.get(0)) && allowRegularPolygon(way.getNodes())) { 134 if (nodes.size() == 1 && ways.size() == 1) { 135 // Regular polygons are allowed only if there is just one way 136 // Should be remove regular are now default for all nodes with no more than 1 referrer. 137 Way way = ways.get(0); 138 if (nodes.size() == 1 && way.containsNode(nodes.get(0)) && allowRegularPolygon(way.getNodes())) 128 139 regular = true; 129 } else if (nodes.size() >= 2) { 130 center = nodes.get(way.containsNode(nodes.get(0)) ? 1 : 0).getEastNorth(); 131 if (nodes.size() == 2) { 140 } 141 if (nodes.size() >= 1) { 142 boolean[] isContained = new boolean[nodes.size()]; 143 for(int i = 0; i < nodes.size(); i++) { 144 Node n = nodes.get(i); 145 isContained[i] = false; 146 for(Way way: ways) 147 if(way.containsNode(n)) { 148 isContained[i] = true; 149 break; 150 } 151 } 152 if(nodes.size() == 1) { 153 if(!isContained[0]) 154 center = nodes.get(0).getEastNorth(); 155 } else { 156 if(!isContained[0] && !isContained[1]) { 157 // 2 nodes outside of way, can't choose one as center 158 new Notification( 159 tr("Please select only one node as center.")) 160 .setIcon(JOptionPane.INFORMATION_MESSAGE) 161 .setDuration(Notification.TIME_SHORT) 162 .show(); 163 return; 164 } else if (!isContained[0]  !isContained[1]) { 165 // 1 node inside and 1 outside, outside is center, inside node define radius 166 center = nodes.get(isContained[0] ? 1 : 0).getEastNorth(); 132 167 radius = distance(nodes.get(0).getEastNorth(), nodes.get(1).getEastNorth()); 168 } else { 169 // 2 nodes inside, define diameter 170 EastNorth en0 = nodes.get(0).getEastNorth(); 171 EastNorth en1 = nodes.get(1).getEastNorth(); 172 center = new EastNorth((en0.east() + en1.east()) / 2, (en0.north() + en1.north()) / 2); 173 radius = distance(en0, en1) / 2; 133 174 } 134 175 } 135 nodes.clear(); 136 } 137 138 for (Node n : way.getNodes()) { 139 if (!nodes.contains(n)) { 140 nodes.add(n); 141 } 142 } 176 } 177 nodes.clear(); 178 179 for(Way way: ways) 180 for (Node n : way.getNodes()) { 181 if (!nodes.contains(n)) { 182 nodes.add(n); 183 } 184 } 143 185 } 144 186 … … 206 248 } 207 249 250 if(!actionAllowed(nodes)) return; 251 208 252 Collection<Command> cmds = new LinkedList<Command>(); 209 253 … … 224 268 pc.angle += angle; 225 269 } 226 } else { // Move each node to that distance from the centre. 227 for (Node n : nodes) { 228 pc = new PolarCoor(n.getEastNorth(), center, 0); 229 pc.radius = radius; 230 EastNorth no = pc.toEastNorth(); 231 cmds.add(new MoveCommand(n, no.east()  n.getEastNorth().east(), no.north()  n.getEastNorth().north())); 232 } 233 } 234 270 } else { // Move each node to that distance from the center. 271 int nodeCount = nodes.size(); 272 // Search first fixed node 273 int startPosition = 0; 274 for(startPosition = 0; startPosition < nodeCount; startPosition++) 275 if(isFixNode(nodes.get(startPosition % nodeCount), sel)) break; 276 int i = startPosition; // Start position for current arc 277 int j; // End position for current arc 278 while(i < startPosition + nodeCount) { 279 for(j = i + 1; j < startPosition + nodeCount; j++) 280 if(isFixNode(nodes.get(j % nodeCount), sel)) break; 281 Node first = nodes.get(i % nodeCount); 282 PolarCoor pcFirst = new PolarCoor(first.getEastNorth(), center, 0); 283 pcFirst.radius = radius; 284 cmds.add(pcFirst.createMoveCommand(first)); 285 if(j > i + 1) { 286 double delta; 287 if(j == i + nodeCount) { 288 delta = 2 * Math.PI / nodeCount; 289 } else { 290 PolarCoor pcLast = new PolarCoor(nodes.get(j % nodeCount).getEastNorth(), center, 0); 291 delta = pcLast.angle  pcFirst.angle; 292 if(delta < 0) // Assume each PolarCoor.angle is in range ]pi; pi] 293 delta += 2*Math.PI; 294 delta /= j  i; 295 } 296 for(int k = i+1; k < j; k++) { 297 PolarCoor p = new PolarCoor(radius, pcFirst.angle + (ki)*delta, center, 0); 298 cmds.add(p.createMoveCommand(nodes.get(k % nodeCount))); 299 } 300 } 301 i = j; // Update start point for next iteration 302 } 303 } 304 235 305 Main.main.undoRedo.add(new SequenceCommand(tr("Align Nodes in Circle"), cmds)); 236 306 Main.map.repaint(); 237 307 } 238 308 309 /** 310 * Check if one or more nodes are outside of download area 311 * @param nodes Nodes to check 312 * @return true if action can be done 313 */ 314 private boolean actionAllowed(Collection<Node> nodes) { 315 boolean outside = false; 316 for(Node n: nodes) 317 if(n.isOutsideDownloadArea()) { 318 outside = true; 319 break; 320 } 321 if(outside) 322 new Notification( 323 tr("One or more nodes involved in this action is outside of the downloaded area.")) 324 .setIcon(JOptionPane.WARNING_MESSAGE) 325 .setDuration(Notification.TIME_SHORT) 326 .show(); 327 return true; 328 } 329 330 /** 331 * Test if angle of a node can be change. 332 * @param n Node 333 * @param sel Selection which action is apply 334 * @return true is this node does't have a fix angle 335 */ 336 private boolean isFixNode(Node n, Collection<OsmPrimitive> sel) { 337 List<OsmPrimitive> referrers = n.getReferrers(); 338 if(referrers.isEmpty()) return false; 339 if(sel.contains(n)  referrers.size() > 1  !sel.contains(referrers.get(0))) return true; 340 return false; 341 } 342 239 343 @Override 240 344 protected void updateEnabledState() { … … 262 366 return true; 263 367 } 368 369 /** 370 * Determines if ways can be joined into a polygon. 371 * @param ways The ways collection to check 372 * @return true if all ways can be joined into a polygon 373 */ 374 protected static boolean checkWaysArePolygon(Collection<Way> ways) { 375 // For each way, nodes strictly between first and last should't be reference by an other way 376 for(Way way: ways) { 377 for(Node node: way.getNodes()) { 378 if(node == way.firstNode()  node == way.lastNode()) continue; 379 for(Way wayOther: ways) { 380 if(way == wayOther) continue; 381 if(node.getReferrers().contains(wayOther)) return false; 382 } 383 } 384 } 385 // Test if ways can be joined 386 Way currentWay = null; 387 Node startNode = null, endNode = null; 388 int used = 0; 389 while(true) { 390 Way nextWay = null; 391 for(Way w: ways) { 392 if(w.firstNode() == w.lastNode()) return ways.size() == 1; 393 if(w == currentWay) continue; 394 if(currentWay == null) { 395 nextWay = w; 396 startNode = w.firstNode(); 397 endNode = w.lastNode(); 398 break; 399 } 400 if(w.firstNode() == endNode) { 401 nextWay = w; 402 endNode = w.lastNode(); 403 break; 404 } 405 if(w.lastNode() == endNode) { 406 nextWay = w; 407 endNode = w.firstNode(); 408 break; 409 } 410 } 411 if(nextWay == null) return false; 412 used += 1; 413 currentWay = nextWay; 414 if(endNode == startNode) return used == ways.size(); 415 } 416 } 264 417 }
Note: See TracChangeset
for help on using the changeset viewer.