Changeset 5746 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2013-02-26T19:17:45+01:00 (12 years ago)
- File:
-
- 1 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/actions/mapmode/ExtrudeAction.java
r5741 r5746 58 58 public class ExtrudeAction extends MapMode implements MapViewPaintable { 59 59 60 enum Mode { extrude, translate, select, create_new }60 enum Mode { extrude, translate, select, create_new, translate_node } 61 61 62 62 private Mode mode = Mode.select; … … 69 69 private long mouseDownTime = 0; 70 70 private WaySegment selectedSegment = null; 71 private Node selectedNode = null; 71 72 private Color mainColor; 72 73 private Stroke mainStroke; … … 85 86 */ 86 87 private List<ReferenceSegment> possibleMoveDirections; 88 89 90 /** 91 * Collection of nodes that is moved 92 */ 93 private Collection<OsmPrimitive> movingNodeList; 87 94 88 95 /** … … 233 240 updateKeyModifiers(e); 234 241 235 Node nearestNode = Main.map.mapView.getNearestNode(e.getPoint(), OsmPrimitive.isSelectablePredicate); 236 242 selectedNode = Main.map.mapView.getNearestNode(e.getPoint(), OsmPrimitive.isSelectablePredicate); 237 243 selectedSegment = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate); 238 boolean dragNode = nearestNode!=null; 239 240 if (selectedSegment == null && nearestNode == null) { 241 // If nothing gets caught, stay in select mode 244 245 // If nothing gets caught, stay in select mode 246 if (selectedSegment == null && selectedNode == null) return; 247 248 if (selectedNode != null) { 249 movingNodeList = new ArrayList<OsmPrimitive>(); 250 movingNodeList.add(selectedNode); 251 calculatePossibleDirectionsByNode(); 252 if (possibleMoveDirections.isEmpty()) { 253 // if no directions fould, do not enter dragging mode 254 return; 255 } 256 mode = Mode.translate_node; 242 257 } else { 243 258 // Otherwise switch to another mode 244 245 259 if (ctrl) { 246 260 mode = Mode.translate; 261 movingNodeList = new ArrayList<OsmPrimitive>(); 262 movingNodeList.add(selectedSegment.getFirstNode()); 263 movingNodeList.add(selectedSegment.getSecondNode()); 247 264 } else if (alt) { 248 265 mode = Mode.create_new; … … 255 272 alwaysCreateNodes = shift; 256 273 } 257 258 259 calculatePossibleDirections(); 260 261 // Signifies that nothing has happened yet 262 newN1en = null; 263 newN2en = null; 264 moveCommand = null; 265 266 Main.map.mapView.addTemporaryLayer(this); 267 268 updateStatusLine(); 269 Main.map.mapView.repaint(); 270 271 // Make note of time pressed 272 mouseDownTime = System.currentTimeMillis(); 273 274 // Make note of mouse position 275 initialMousePos = e.getPoint(); 276 } 277 } 274 calculatePossibleDirectionsBySegment(); 275 } 276 277 // Signifies that nothing has happened yet 278 newN1en = null; 279 newN2en = null; 280 moveCommand = null; 281 282 Main.map.mapView.addTemporaryLayer(this); 283 284 updateStatusLine(); 285 Main.map.mapView.repaint(); 286 287 // Make note of time pressed 288 mouseDownTime = System.currentTimeMillis(); 289 290 // Make note of mouse position 291 initialMousePos = e.getPoint(); 292 } 278 293 279 294 /** … … 308 323 if (mode == Mode.extrude || mode == Mode.create_new) { 309 324 //nothing here 310 } else if (mode == Mode.translate ) {325 } else if (mode == Mode.translate_node || mode == Mode.translate) { 311 326 //move nodes to new position 312 327 if (moveCommand == null) { 313 328 //make a new move command 314 Collection<OsmPrimitive> nodelist = new LinkedList<OsmPrimitive>(); 315 nodelist.add(selectedSegment.getFirstNode()); 316 nodelist.add(selectedSegment.getSecondNode()); 317 moveCommand = new MoveCommand(nodelist, bestMovement.getX(), bestMovement.getY()); 329 moveCommand = new MoveCommand(movingNodeList, bestMovement.getX(), bestMovement.getY()); 318 330 Main.main.undoRedo.add(moveCommand); 319 331 } else { … … 340 352 if (mode == Mode.create_new) { 341 353 if (e.getPoint().distance(initialMousePos) > 10 && newN1en != null) { 342 // crete a new rectangle 343 Collection<Command> cmds = new LinkedList<Command>(); 344 Node third = new Node(newN2en); 345 Node fourth = new Node(newN1en); 346 Way wnew = new Way(); 347 wnew.addNode(selectedSegment.getFirstNode()); 348 wnew.addNode(selectedSegment.getSecondNode()); 349 wnew.addNode(third); 350 wnew.addNode(fourth); 351 // ... and close the way 352 wnew.addNode(selectedSegment.getFirstNode()); 353 // undo support 354 cmds.add(new AddCommand(third)); 355 cmds.add(new AddCommand(fourth)); 356 cmds.add(new AddCommand(wnew)); 357 Command c = new SequenceCommand(tr("Extrude Way"), cmds); 358 Main.main.undoRedo.add(c); 359 getCurrentDataSet().setSelected(wnew); 354 createNewRectangle(); 360 355 } 361 356 } else if (mode == Mode.extrude) { 362 357 if( e.getClickCount() == 2 && e.getPoint().equals(initialMousePos) ) { 363 // double click add a new node 364 // Should maybe do the same as in DrawAction and fetch all nearby segments? 365 WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate); 366 if (ws != null) { 367 Node n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY())); 368 EastNorth A = ws.getFirstNode().getEastNorth(); 369 EastNorth B = ws.getSecondNode().getEastNorth(); 370 n.setEastNorth(Geometry.closestPointToSegment(A, B, n.getEastNorth())); 371 Way wnew = new Way(ws.way); 372 wnew.addNode(ws.lowerIndex+1, n); 373 SequenceCommand cmds = new SequenceCommand(tr("Add a new node to an existing way"), 374 new AddCommand(n), new ChangeCommand(ws.way, wnew)); 375 Main.main.undoRedo.add(cmds); 376 } 358 // double click adds a new node 359 addNewNode(e); 377 360 } 378 361 else if (e.getPoint().distance(initialMousePos) > 10 && newN1en != null && selectedSegment != null) { 379 // create extrusion 380 381 Collection<Command> cmds = new LinkedList<Command>(); 382 Way wnew = new Way(selectedSegment.way); 383 int insertionPoint = selectedSegment.lowerIndex + 1; 384 385 //find if the new points overlap existing segments (in case of 90 degree angles) 386 Node prevNode = getPreviousNode(selectedSegment.lowerIndex); 387 boolean nodeOverlapsSegment = prevNode != null && Geometry.segmentsParallel(initialN1en, prevNode.getEastNorth(), initialN1en, newN1en); 388 boolean hasOtherWays = this.hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way); 389 390 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 391 //move existing node 392 Node n1Old = selectedSegment.getFirstNode(); 393 cmds.add(new MoveCommand(n1Old, Main.getProjection().eastNorth2latlon(newN1en))); 394 } else { 395 //introduce new node 396 Node n1New = new Node(Main.getProjection().eastNorth2latlon(newN1en)); 397 wnew.addNode(insertionPoint, n1New); 398 insertionPoint ++; 399 cmds.add(new AddCommand(n1New)); 400 } 401 402 //find if the new points overlap existing segments (in case of 90 degree angles) 403 Node nextNode = getNextNode(selectedSegment.lowerIndex + 1); 404 nodeOverlapsSegment = nextNode != null && Geometry.segmentsParallel(initialN2en, nextNode.getEastNorth(), initialN2en, newN2en); 405 hasOtherWays = hasNodeOtherWays(selectedSegment.getSecondNode(), selectedSegment.way); 406 407 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 408 //move existing node 409 Node n2Old = selectedSegment.getSecondNode(); 410 cmds.add(new MoveCommand(n2Old, Main.getProjection().eastNorth2latlon(newN2en))); 411 } else { 412 //introduce new node 413 Node n2New = new Node(Main.getProjection().eastNorth2latlon(newN2en)); 414 wnew.addNode(insertionPoint, n2New); 415 insertionPoint ++; 416 cmds.add(new AddCommand(n2New)); 417 } 418 419 //the way was a single segment, close the way 420 if (wnew.getNodesCount() == 4) { 421 wnew.addNode(selectedSegment.getFirstNode()); 422 } 423 424 cmds.add(new ChangeCommand(selectedSegment.way, wnew)); 425 Command c = new SequenceCommand(tr("Extrude Way"), cmds); 426 Main.main.undoRedo.add(c); 362 // main extrusion commands 363 performExtrusion(); 427 364 } 428 } else if (mode == Mode.translate ) {365 } else if (mode == Mode.translate || mode == Mode.translate_node) { 429 366 //Commit translate 430 367 //the move command is already committed in mouseDragged … … 445 382 } 446 383 } 447 384 385 /** 386 * Insert node into nearby segment 387 * @param e - current mouse point 388 */ 389 private void addNewNode(MouseEvent e) { 390 // Should maybe do the same as in DrawAction and fetch all nearby segments? 391 WaySegment ws = Main.map.mapView.getNearestWaySegment(e.getPoint(), OsmPrimitive.isSelectablePredicate); 392 if (ws != null) { 393 Node n = new Node(Main.map.mapView.getLatLon(e.getX(), e.getY())); 394 EastNorth A = ws.getFirstNode().getEastNorth(); 395 EastNorth B = ws.getSecondNode().getEastNorth(); 396 n.setEastNorth(Geometry.closestPointToSegment(A, B, n.getEastNorth())); 397 Way wnew = new Way(ws.way); 398 wnew.addNode(ws.lowerIndex+1, n); 399 SequenceCommand cmds = new SequenceCommand(tr("Add a new node to an existing way"), 400 new AddCommand(n), new ChangeCommand(ws.way, wnew)); 401 Main.main.undoRedo.add(cmds); 402 } 403 } 404 405 private void createNewRectangle() { 406 if (selectedSegment == null) return; 407 // crete a new rectangle 408 Collection<Command> cmds = new LinkedList<Command>(); 409 Node third = new Node(newN2en); 410 Node fourth = new Node(newN1en); 411 Way wnew = new Way(); 412 wnew.addNode(selectedSegment.getFirstNode()); 413 wnew.addNode(selectedSegment.getSecondNode()); 414 wnew.addNode(third); 415 wnew.addNode(fourth); 416 // ... and close the way 417 wnew.addNode(selectedSegment.getFirstNode()); 418 // undo support 419 cmds.add(new AddCommand(third)); 420 cmds.add(new AddCommand(fourth)); 421 cmds.add(new AddCommand(wnew)); 422 Command c = new SequenceCommand(tr("Extrude Way"), cmds); 423 Main.main.undoRedo.add(c); 424 getCurrentDataSet().setSelected(wnew); 425 } 426 427 /** 428 * Do actual extrusion of @field selectedSegment 429 */ 430 private void performExtrusion() { 431 // create extrusion 432 Collection<Command> cmds = new LinkedList<Command>(); 433 Way wnew = new Way(selectedSegment.way); 434 int insertionPoint = selectedSegment.lowerIndex + 1; 435 436 //find if the new points overlap existing segments (in case of 90 degree angles) 437 Node prevNode = getPreviousNode(selectedSegment.lowerIndex); 438 boolean nodeOverlapsSegment = prevNode != null && Geometry.segmentsParallel(initialN1en, prevNode.getEastNorth(), initialN1en, newN1en); 439 boolean hasOtherWays = this.hasNodeOtherWays(selectedSegment.getFirstNode(), selectedSegment.way); 440 441 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 442 //move existing node 443 Node n1Old = selectedSegment.getFirstNode(); 444 cmds.add(new MoveCommand(n1Old, Main.getProjection().eastNorth2latlon(newN1en))); 445 } else { 446 //introduce new node 447 Node n1New = new Node(Main.getProjection().eastNorth2latlon(newN1en)); 448 wnew.addNode(insertionPoint, n1New); 449 insertionPoint ++; 450 cmds.add(new AddCommand(n1New)); 451 } 452 453 //find if the new points overlap existing segments (in case of 90 degree angles) 454 Node nextNode = getNextNode(selectedSegment.lowerIndex + 1); 455 nodeOverlapsSegment = nextNode != null && Geometry.segmentsParallel(initialN2en, nextNode.getEastNorth(), initialN2en, newN2en); 456 hasOtherWays = hasNodeOtherWays(selectedSegment.getSecondNode(), selectedSegment.way); 457 458 if (nodeOverlapsSegment && !alwaysCreateNodes && !hasOtherWays) { 459 //move existing node 460 Node n2Old = selectedSegment.getSecondNode(); 461 cmds.add(new MoveCommand(n2Old, Main.getProjection().eastNorth2latlon(newN2en))); 462 } else { 463 //introduce new node 464 Node n2New = new Node(Main.getProjection().eastNorth2latlon(newN2en)); 465 wnew.addNode(insertionPoint, n2New); 466 insertionPoint ++; 467 cmds.add(new AddCommand(n2New)); 468 } 469 470 //the way was a single segment, close the way 471 if (wnew.getNodesCount() == 4) { 472 wnew.addNode(selectedSegment.getFirstNode()); 473 } 474 475 cmds.add(new ChangeCommand(selectedSegment.way, wnew)); 476 Command c = new SequenceCommand(tr("Extrude Way"), cmds); 477 Main.main.undoRedo.add(c); 478 } 479 448 480 /** 449 481 * This method tests if a node has other ways apart from the given one. … … 468 500 469 501 EastNorth initialMouseEn = Main.map.mapView.getEastNorth(initialMousePos.x, initialMousePos.y); 470 EastNorth mouseMovement = new EastNorth(mouseEn.getX() - initialMouseEn.getX(), mouseEn.getY() - initialMouseEn.getY());471 502 EastNorth mouseMovement = initialMouseEn.sub(mouseEn); 503 472 504 double bestDistance = Double.POSITIVE_INFINITY; 473 505 EastNorth bestMovement = null; … … 501 533 private static EastNorth calculateSegmentOffset(EastNorth segmentP1, EastNorth segmentP2, EastNorth moveDirection, 502 534 EastNorth targetPos) { 503 EastNorth intersectionPoint = Geometry.getLineLineIntersection(segmentP1, segmentP2, targetPos, 504 new EastNorth(targetPos.getX() + moveDirection.getX(), targetPos.getY() + moveDirection.getY())); 535 EastNorth intersectionPoint; 536 if (segmentP1.distanceSq(segmentP2)>1e-7) { 537 intersectionPoint = Geometry.getLineLineIntersection(segmentP1, segmentP2, targetPos, targetPos.add(moveDirection)); 538 } else { 539 intersectionPoint = Geometry.closestPointToLine(targetPos, targetPos.add(moveDirection), segmentP1); 540 } 505 541 506 542 if (intersectionPoint == null) … … 508 544 else 509 545 //return distance form base to target position 510 return new EastNorth(targetPos.getX() - intersectionPoint.getX(), 511 targetPos.getY() - intersectionPoint.getY()); 546 return intersectionPoint.sub(targetPos); 512 547 } 513 548 … … 515 550 * Gather possible move directions - perpendicular to the selected segment and parallel to neighbor segments 516 551 */ 517 private void calculatePossibleDirections () {552 private void calculatePossibleDirectionsBySegment() { 518 553 // remember initial positions for segment nodes. 519 554 initialN1en = selectedSegment.getFirstNode().getEastNorth(); … … 549 584 550 585 /** 586 * Gather possible move directions - along all adjacent segments 587 */ 588 private void calculatePossibleDirectionsByNode() { 589 // remember initial positions for segment nodes. 590 initialN1en = selectedNode.getEastNorth(); 591 initialN2en = initialN1en; 592 possibleMoveDirections = new ArrayList<ReferenceSegment>(); 593 for (OsmPrimitive p: selectedNode.getReferrers()) { 594 if (p instanceof Way && p.isUsable()) { 595 for (Node neighbor: ((Way) p).getNeighbours(selectedNode)) { 596 EastNorth en = neighbor.getEastNorth(); 597 possibleMoveDirections.add(new ReferenceSegment(new EastNorth( 598 initialN1en.getX() - en.getX(), 599 initialN1en.getY() - en.getY() 600 ), initialN1en, en, false)); 601 } 602 } 603 } 604 } 605 606 /** 551 607 * Gets a node from selected way before given index. 552 608 * @param index index of current node … … 604 660 } 605 661 662 @Override 606 663 public void paint(Graphics2D g, MapView mv, Bounds box) { 607 664 Graphics2D g2 = g; … … 650 707 } 651 708 } 652 } else if (mode == Mode.translate ) {709 } else if (mode == Mode.translate || mode == Mode.translate_node) { 653 710 g2.setColor(mainColor); 654 g2.setStroke(oldLineStroke); 655 // Highlight the old segment 656 g2.setStroke(mainStroke); 657 Line2D oldline = new Line2D.Double(p1, p2); 658 g2.draw(oldline); 711 if (p1.distance(p2) < 3) { 712 g2.setStroke(mainStroke); 713 g2.drawOval((int)(p1.x-symbolSize/2), (int)(p1.y-symbolSize/2), 714 (int)(symbolSize), (int)(symbolSize)); 715 } else { 716 Line2D oldline = new Line2D.Double(p1, p2); 717 g2.setStroke(oldLineStroke); 718 g2.draw(oldline); 719 } 659 720 660 721 if (activeMoveDirection != null) {
Note:
See TracChangeset
for help on using the changeset viewer.