Changeset 6893 in josm
- Timestamp:
- 2014-03-02T12:06:31+01:00 (11 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/AlignInLineAction.java
r6380 r6893 9 9 import java.util.ArrayList; 10 10 import java.util.Collection; 11 import java.util.HashMap; 12 import java.util.HashSet; 11 13 import java.util.List; 12 14 … … 69 71 70 72 private void showWarning() { 71 new Notification( 72 tr("Please select at least three nodes.")) 73 .setIcon(JOptionPane.INFORMATION_MESSAGE) 74 .show(); 73 showWarning(tr("Please select at least three nodes.")); 74 } 75 76 private void showWarning(String msg) { 77 new Notification(msg) 78 .setIcon(JOptionPane.INFORMATION_MESSAGE) 79 .show(); 75 80 } 76 81 … … 114 119 //// Decide what to align based on selection: 115 120 116 /// Only ways selected -> Align their nodes. 117 if ((selectedNodes.isEmpty()) && (selectedWays.size() == 1)) { // TODO: handle multiple ways 118 for (Way way : selectedWays) { 119 nodes.addAll(way.getNodes()); 120 } 121 // use the nodes furthest apart as anchors 122 nodePairFurthestApart(nodes, anchors); 121 /// Only ways selected -> For each way align their nodes taking care of intersection 122 if(selectedNodes.isEmpty() && !selectedWays.isEmpty()) { 123 alignMultiWay(selectedWays); 124 return; 123 125 } 124 126 /// More than 3 nodes selected -> align those nodes … … 221 223 } 222 224 225 /** 226 * Align way in case of multiple way #6819 227 * @param ways Collection of way to align 228 */ 229 private void alignMultiWay(Collection<Way> ways) { 230 // Collect all nodes and compute line equation 231 HashSet<Node> nodes = new HashSet<Node>(); 232 HashMap<Way, Line> lines = new HashMap<Way, Line>(); 233 for(Way w: ways) { 234 if(w.firstNode() == w.lastNode()) { 235 showWarning(tr("Can not align a polygon. Abort.")); 236 return; 237 } 238 nodes.addAll(w.getNodes()); 239 lines.put(w, new Line(w)); 240 } 241 Collection<Command> cmds = new ArrayList<Command>(nodes.size()); 242 List<Way> referers = new ArrayList<Way>(ways.size()); 243 for(Node n: nodes) { 244 referers.clear(); 245 for(OsmPrimitive o: n.getReferrers()) 246 if(ways.contains(o)) 247 referers.add((Way) o); 248 if(referers.size() == 1) { 249 Way way = referers.get(0); 250 if(n == way.firstNode() || n == way.lastNode()) continue; 251 cmds.add(lines.get(way).projectionCommand(n)); 252 } 253 else if(referers.size() == 2) { 254 Command cmd = lines.get(referers.get(0)).intersectionCommand(n, lines.get(referers.get(1))); 255 if(cmd == null) { 256 showWarning(tr("Two parallels ways found. Abort.")); 257 return; 258 } 259 cmds.add(cmd); 260 } 261 else { 262 showWarning(tr("Intersection of three or more ways can not be solved. Abort.")); 263 return; 264 } 265 } 266 Main.main.undoRedo.add(new SequenceCommand(tr("Align Nodes in Line"), cmds)); 267 Main.map.repaint(); 268 } 269 270 /** 271 * Class that describe a line 272 */ 273 private class Line { 274 275 /** 276 * Line equation ax + by + c = 0 277 * Such as a^2 + b^2 = 1, ie (-b, a) is a unit vector of line 278 */ 279 private double a, b, c; // Line equation ax+by+c=0 280 /** 281 * (xM, yM) are coordinate of a point of the line 282 */ 283 private double xM, yM; // Coordinate of a point of the line 284 285 /** 286 * Init a line equation from a way. 287 * @param way 288 */ 289 public Line(Way way) { 290 xM = way.firstNode().getEastNorth().getX(); 291 yM = way.firstNode().getEastNorth().getY(); 292 double xB = way.lastNode().getEastNorth().getX(); 293 double yB = way.lastNode().getEastNorth().getY(); 294 a = yB - yM; 295 b = xM - xB; 296 double norm = Math.sqrt(a*a + b*b); 297 if (norm == 0) { 298 norm = 1; 299 } 300 a /= norm; 301 b /= norm; 302 c = -(a*xM + b*yM); 303 } 304 305 /** 306 * Orthogonal projection of a node N along this line. 307 * @param n Node to be projected 308 * @return The command that do the projection of this node 309 */ 310 public Command projectionCommand(Node n) { 311 double s = (xM - n.getEastNorth().getX()) * a + (yM - n.getEastNorth().getY()) * b; 312 return new MoveCommand(n, a*s, b*s); 313 } 314 315 /** 316 * Intersection of two line. 317 * @param n Node to move to the intersection 318 * @param other Second line for intersection 319 * @return The command that move the node or null if line are parallels 320 */ 321 public Command intersectionCommand(Node n, Line other) { 322 double d = this.a * other.b - other.a * this.b; 323 if(d == 0) return null; 324 double x = (this.b * other.c - other.b * this.c) / d; 325 double y = (other.a * this.c - this.a * other.c) / d; 326 return new MoveCommand(n, x - n.getEastNorth().getX(), y - n.getEastNorth().getY()); 327 } 328 } 329 223 330 @Override 224 331 protected void updateEnabledState() {
Note:
See TracChangeset
for help on using the changeset viewer.