Changeset 578 in josm for trunk/src/org/openstreetmap
- Timestamp:
- 2008-03-06T13:51:08+01:00 (17 years ago)
- Location:
- trunk/src/org/openstreetmap/josm/gui
- Files:
-
- 2 edited
Legend:
- Unmodified
- Added
- Removed
-
trunk/src/org/openstreetmap/josm/gui/layer/GpxLayer.java
r575 r578 25 25 import java.net.UnknownHostException; 26 26 import java.util.Iterator; 27 import java.util.Collections; 28 import java.util.Comparator; 27 29 28 30 import javax.swing.AbstractAction; … … 46 48 import org.openstreetmap.josm.actions.SaveAsAction; 47 49 import org.openstreetmap.josm.actions.RenameLayerAction; 50 import org.openstreetmap.josm.data.coor.EastNorth; 48 51 import org.openstreetmap.josm.data.gpx.GpxData; 49 52 import org.openstreetmap.josm.data.gpx.GpxTrack; … … 499 502 String uri = "file:".concat(wavFile.getAbsolutePath()); 500 503 MarkerLayer ml = new MarkerLayer(new GpxData(), tr("Audio markers from {0}", name), associatedFile, me); 501 502 // (a) try explicit waypoints - unless suppressed 504 505 Collection<WayPoint> waypoints = new ArrayList<WayPoint>(); 506 boolean timedMarkersOmitted = false; 507 boolean untimedMarkersOmitted = false; 508 509 // determine time of first point in track 510 double firstTime = -1.0; 511 if (data.tracks != null && ! data.tracks.isEmpty()) { 512 for (GpxTrack track : data.tracks) { 513 if (track.trackSegs == null) continue; 514 for (Collection<WayPoint> seg : track.trackSegs) { 515 for (WayPoint w : seg) { 516 firstTime = w.time; 517 break; 518 } 519 if (firstTime >= 0.0) break; 520 } 521 if (firstTime >= 0.0) break; 522 } 523 } 524 if (firstTime < 0.0) { 525 JOptionPane.showMessageDialog(Main.parent, tr("No GPX track available in layer to associate audio with.")); 526 return; 527 } 528 529 // (a) try explicit timestamped waypoints - unless suppressed 503 530 if (Main.pref.getBoolean("marker.audiofromexplicitwaypoints", true) && 504 data.waypoints != null && 505 ! data.waypoints.isEmpty()) 531 data.waypoints != null && ! data.waypoints.isEmpty()) 506 532 { 507 double firstTime = -1.0;508 533 for (WayPoint w : data.waypoints) { 509 if (firstTime < 0.0) firstTime = w.time; 510 double offset = w.time - firstTime; 511 String name = w.attr.containsKey("name") ? w.getString("name") : 512 w.attr.containsKey("desc") ? w.getString("desc") : 513 AudioMarker.inventName(offset); 514 AudioMarker am = AudioMarker.create(w.latlon, 515 name, uri, ml, w.time, offset); 516 ml.data.add(am); 534 if (w.time > firstTime) { 535 waypoints.add(w); 536 } else if (w.time > 0.0) { 537 timedMarkersOmitted = true; 538 } 517 539 } 518 540 } 519 541 520 // (b) use explicitly named track points, again unless suppressed 521 if (ml.data.isEmpty() && 522 Main.pref.getBoolean("marker.namedtrackpoints") && 523 data.tracks != null && 524 ! data.tracks.isEmpty()) 542 // (b) try explicit waypoints without timestamps - unless suppressed 543 if (Main.pref.getBoolean("marker.audiofromuntimedwaypoints", true) && 544 data.waypoints != null && ! data.waypoints.isEmpty()) 525 545 { 526 double firstTime = -1.0; 546 for (WayPoint w : data.waypoints) { 547 if (waypoints.contains(w)) { continue; } 548 WayPoint wNear = nearestPointOnTrack(w.eastNorth, 10.0e-7 /* about 25m */); 549 if (wNear != null) { 550 WayPoint wc = new WayPoint(w.latlon); 551 wc.time = wNear.time; 552 if (w.attr.containsKey("name")) wc.attr.put("name", w.getString("name")); 553 waypoints.add(wc); 554 } else { 555 untimedMarkersOmitted = true; 556 } 557 } 558 } 559 560 // (c) use explicitly named track points, again unless suppressed 561 if ((Main.pref.getBoolean("marker.audiofromnamedtrackpoints", Main.pref.getBoolean("marker.namedtrackpoints") /* old name */)) && 562 data.tracks != null && ! data.tracks.isEmpty()) 563 { 527 564 for (GpxTrack track : data.tracks) { 565 if (track.trackSegs == null) continue; 528 566 for (Collection<WayPoint> seg : track.trackSegs) { 529 567 for (WayPoint w : seg) { 530 String name; 531 if (w.attr.containsKey("name")) 532 name = w.getString("name"); 533 else if (w.attr.containsKey("desc")) 534 name = w.getString("desc"); 535 else 536 continue; 537 if (firstTime < 0.0) firstTime = w.time; 538 double offset = w.time - firstTime; 539 AudioMarker am = AudioMarker.create(w.latlon, 540 name, uri, ml, w.time, offset); 541 ml.data.add(am); 568 if (w.attr.containsKey("name") || w.attr.containsKey("desc")) { 569 waypoints.add(w); 570 } 542 571 } 543 572 } … … 545 574 } 546 575 547 // ( c) analyse audio for spoken markers here, in due course576 // (d) analyse audio for spoken markers here, in due course 548 577 549 // (d) simply add a single marker at the start of the track 550 if (ml.data.isEmpty() && 551 data.tracks != null && 552 ! data.tracks.isEmpty()) 578 // (e) simply add a single marker at the start of the track 579 if ((Main.pref.getBoolean("marker.audiofromstart") || waypoints.isEmpty()) && 580 data.tracks != null && ! data.tracks.isEmpty()) 553 581 { 582 boolean gotOne = false; 554 583 for (GpxTrack track : data.tracks) { 584 if (track.trackSegs == null) continue; 555 585 for (Collection<WayPoint> seg : track.trackSegs) { 556 586 for (WayPoint w : seg) { 557 AudioMarker am = AudioMarker.create(w.latlon, 558 tr("start"), uri, ml, w.time, 0.0); 559 ml.data.add(am); 587 WayPoint wStart = new WayPoint(w.latlon); 588 wStart.attr.put("name", "start"); 589 wStart.time = w.time; 590 waypoints.add(wStart); 591 gotOne = true; 560 592 break; 561 593 } 562 if ( ! ml.data.isEmpty()) break;594 if (gotOne) break; 563 595 } 564 if ( ! ml.data.isEmpty()) break;596 if (gotOne) break; 565 597 } 566 598 } 599 600 /* we must have got at least one waypoint now */ 567 601 568 if (! ml.data.isEmpty()) { 569 Main.main.addLayer(ml); 570 } else { 571 JOptionPane.showMessageDialog(Main.parent, tr("Nothing available to associate audio with.")); 572 } 602 Collections.sort((ArrayList<WayPoint>) waypoints, new Comparator<WayPoint>() { 603 public int compare(WayPoint a, WayPoint b) { 604 return a.time <= b.time ? -1 : 1; 605 } 606 }); 607 608 firstTime = -1.0; /* this time of the first waypoint, not first trackpoint */ 609 for (WayPoint w : waypoints) { 610 if (firstTime < 0.0) firstTime = w.time; 611 double offset = w.time - firstTime; 612 String name; 613 if (w.attr.containsKey("name")) 614 name = w.getString("name"); 615 else if (w.attr.containsKey("desc")) 616 name = w.getString("desc"); 617 else 618 name = AudioMarker.inventName(offset); 619 AudioMarker am = AudioMarker.create(w.latlon, 620 name, uri, ml, w.time, offset); 621 ml.data.add(am); 622 } 623 Main.main.addLayer(ml); 624 625 if (timedMarkersOmitted) { 626 JOptionPane.showMessageDialog(Main.parent, tr("Some waypoints with timestamps from before the start of the track were omitted.")); 627 } 628 if (untimedMarkersOmitted) { 629 JOptionPane.showMessageDialog(Main.parent, tr("Some waypoints which were too far from the track to sensibly estimate their time were omitted.")); 630 } 631 } 632 633 /** 634 * Makes a WayPoint at the projection of point P onto the track providing P is 635 * less than tolerance away from the track 636 637 * @param P : the point to determine the projection for 638 * @param tolerance : must be no further than this from the track 639 * @return the closest point on the track to P, which may be the 640 * first or last point if off the end of a segment, or may be null if 641 * nothing close enough 642 */ 643 public WayPoint nearestPointOnTrack(EastNorth P, double tolerance) { 644 /* 645 * assume the coordinates of P are xp,yp, and those of a section of track 646 * between two trackpoints are R=xr,yr and S=xs,ys. Let N be the projected point. 647 * 648 * The equation of RS is Ax + By + C = 0 where 649 * A = ys - yr 650 * B = xr - xs 651 * C = - Axr - Byr 652 * 653 * Also, note that the distance RS^2 is A^2 + B^2 654 * 655 * If RS^2 == 0.0 ignore the degenerate section of track 656 * 657 * PN^2 = (Axp + Byp + C)^2 / RS^2 658 * that is the distance from P to the line 659 * 660 * so if PN^2 is less than PNmin^2 (initialized to tolerance) we can reject 661 * the line; otherwise... 662 * determine if the projected poijnt lies within the bounds of the line: 663 * PR^2 - PN^2 <= RS^2 and PS^2 - PN^2 <= RS^2 664 * 665 * where PR^2 = (xp - xr)^2 + (yp-yr)^2 666 * and PS^2 = (xp - xs)^2 + (yp-ys)^2 667 * 668 * If so, calculate N as 669 * xn = xr + (RN/RS) B 670 * yn = y1 + (RN/RS) A 671 * 672 * where RN = sqrt(PR^2 - PN^2) 673 */ 674 675 double PNminsq = tolerance * tolerance; 676 EastNorth bestEN = null; 677 double bestTime = 0.0; 678 double px = P.east(); 679 double py = P.north(); 680 double rx = 0.0, ry = 0.0, sx, sy, x, y; 681 if (data.tracks == null) return null; 682 for (GpxTrack track : data.tracks) { 683 if (track.trackSegs == null) continue; 684 for (Collection<WayPoint> seg : track.trackSegs) { 685 WayPoint R = null; 686 for (WayPoint S : seg) { 687 if (R == null) { 688 R = S; 689 rx = R.eastNorth.east(); 690 ry = R.eastNorth.north(); 691 x = px - rx; 692 y = py - ry; 693 double PRsq = x * x + y * y; 694 if (PRsq < PNminsq) { 695 PNminsq = PRsq; 696 bestEN = R.eastNorth; 697 bestTime = R.time; 698 } 699 } else { 700 sx = S.eastNorth.east(); 701 sy = S.eastNorth.north(); 702 double A = sy - ry; 703 double B = rx - sx; 704 double C = - A * rx - B * ry; 705 double RSsq = A * A + B * B; 706 if (RSsq == 0.0) continue; 707 double PNsq = A * px + B * py + C; 708 PNsq = PNsq * PNsq / RSsq; 709 if (PNsq < PNminsq) { 710 x = px - rx; 711 y = py - ry; 712 double PRsq = x * x + y * y; 713 x = px - sx; 714 y = py - sy; 715 double PSsq = x * x + y * y; 716 if (PRsq - PNsq <= RSsq && PSsq - PNsq <= RSsq) { 717 double RNoverRS = Math.sqrt((PRsq - PNsq)/RSsq); 718 double nx = rx - RNoverRS * B; 719 double ny = ry + RNoverRS * A; 720 bestEN = new EastNorth(nx, ny); 721 bestTime = R.time + RNoverRS * (S.time - R.time); 722 PNminsq = PNsq; 723 } 724 } 725 R = S; 726 rx = sx; 727 ry = sy; 728 } 729 } 730 if (R != null) { 731 /* if there is only one point in the seg, it will do this twice, but no matter */ 732 rx = R.eastNorth.east(); 733 ry = R.eastNorth.north(); 734 x = px - rx; 735 y = py - ry; 736 double PRsq = x * x + y * y; 737 if (PRsq < PNminsq) { 738 PNminsq = PRsq; 739 bestEN = R.eastNorth; 740 bestTime = R.time; 741 } 742 743 } 744 } 745 } 746 if (bestEN == null) return null; 747 WayPoint best = new WayPoint(Main.proj.eastNorth2latlon(bestEN)); 748 best.time = bestTime; 749 return best; 573 750 } 574 751 } -
trunk/src/org/openstreetmap/josm/gui/preferences/AudioPreference.java
r573 r578 30 30 private JCheckBox markerButtonLabels = new JCheckBox(tr("Label audio (and image and web) markers.")); 31 31 private JCheckBox markerAudioTraceVisible = new JCheckBox(tr("Display live audio trace.")); 32 private JCheckBox markersNamedTrackpoints = new JCheckBox(tr("Create audio markers from named trackpoints."));33 32 private JCheckBox makeAutoMarkers = new JCheckBox(tr("Create non-audio markers when reading GPX.")); 34 private JCheckBox audioMarkersFromExplicitWaypoints = new JCheckBox(tr("Import audio uses explicit waypoints.")); 33 34 // various methods of making markers on import audio 35 private JCheckBox audioMarkersFromExplicitWaypoints = new JCheckBox(tr("Explicit waypoints with valid timestamps.")); 36 private JCheckBox audioMarkersFromUntimedWaypoints = new JCheckBox(tr("Explicit waypoints with time estimated from track position.")); 37 private JCheckBox audioMarkersFromNamedTrackpoints = new JCheckBox(tr("Named trackpoints.")); 38 private JCheckBox audioMarkersFromStart = new JCheckBox(tr("Start of track (will always do this if no other markers available).")); 35 39 36 40 private JTextField audioLeadIn = new JTextField(8); … … 57 61 if (!markerAudioTraceVisible.isSelected()) 58 62 markerAudioTraceVisible.setSelected(false); 59 markerAudioTraceVisible.setEnabled(markerAudioTraceVisible.isSelected());60 63 } 61 64 }); … … 69 72 if (!markerButtonLabels.isSelected()) 70 73 markerButtonLabels.setSelected(false); 71 markerButtonLabels.setEnabled(markerButtonLabels.isSelected());72 74 } 73 75 }); … … 76 78 gui.audio.add(markerButtonLabels, GBC.eol().insets(0,0,0,0)); 77 79 78 // markersNamedTrackpoints79 markersNamedTrackpoints.addActionListener(new ActionListener(){80 public void actionPerformed(ActionEvent e) {81 if (!markersNamedTrackpoints.isSelected())82 markersNamedTrackpoints.setSelected(false);83 markersNamedTrackpoints.setEnabled(markersNamedTrackpoints.isSelected());84 }85 });86 markersNamedTrackpoints.setSelected(Main.pref.getBoolean("marker.namedtrackpoints"));87 markersNamedTrackpoints.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions."));88 gui.audio.add(markersNamedTrackpoints, GBC.eol().insets(0,0,0,0));89 90 80 // makeAutoMarkers 91 81 makeAutoMarkers.addActionListener(new ActionListener(){ … … 93 83 if (!makeAutoMarkers.isSelected()) 94 84 makeAutoMarkers.setSelected(false); 95 makeAutoMarkers.setEnabled(makeAutoMarkers.isSelected());96 85 } 97 86 }); … … 100 89 gui.audio.add(makeAutoMarkers, GBC.eol().insets(0,0,0,0)); 101 90 91 gui.audio.add(new JLabel(tr("When importing audio, make markers from...")), GBC.eol()); 92 102 93 // audioMarkersFromExplicitWaypoints 103 94 audioMarkersFromExplicitWaypoints.addActionListener(new ActionListener(){ … … 105 96 if (!audioMarkersFromExplicitWaypoints.isSelected()) 106 97 audioMarkersFromExplicitWaypoints.setSelected(false); 107 audioMarkersFromExplicitWaypoints.setEnabled(audioMarkersFromExplicitWaypoints.isSelected());108 98 } 109 99 }); 110 100 audioMarkersFromExplicitWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromexplicitwaypoints", true)); 111 101 audioMarkersFromExplicitWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer.")); 112 gui.audio.add(audioMarkersFromExplicitWaypoints, GBC.eol().insets(0,0,0,0)); 102 gui.audio.add(audioMarkersFromExplicitWaypoints, GBC.eol().insets(10,0,0,0)); 103 104 // audioMarkersFromUntimedWaypoints 105 audioMarkersFromUntimedWaypoints.addActionListener(new ActionListener(){ 106 public void actionPerformed(ActionEvent e) { 107 if (!audioMarkersFromUntimedWaypoints.isSelected()) 108 audioMarkersFromUntimedWaypoints.setSelected(false); 109 } 110 }); 111 audioMarkersFromUntimedWaypoints.setSelected(Main.pref.getBoolean("marker.audiofromuntimedwaypoints", true)); 112 audioMarkersFromUntimedWaypoints.setToolTipText(tr("When importing audio, apply it to any waypoints in the GPX layer.")); 113 gui.audio.add(audioMarkersFromUntimedWaypoints, GBC.eol().insets(10,0,0,0)); 114 115 // audioMarkersFromNamedTrackpoints 116 audioMarkersFromNamedTrackpoints.addActionListener(new ActionListener(){ 117 public void actionPerformed(ActionEvent e) { 118 if (!audioMarkersFromNamedTrackpoints.isSelected()) 119 audioMarkersFromNamedTrackpoints.setSelected(false); 120 } 121 }); 122 audioMarkersFromNamedTrackpoints.setSelected(Main.pref.getBoolean("marker.audiofromnamedtrackpoints", Main.pref.getBoolean("marker.namedtrackpoints"))); 123 audioMarkersFromNamedTrackpoints.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions.")); 124 gui.audio.add(audioMarkersFromNamedTrackpoints, GBC.eol().insets(10,0,0,0)); 125 126 // audioMarkersFromStart 127 audioMarkersFromStart.addActionListener(new ActionListener(){ 128 public void actionPerformed(ActionEvent e) { 129 if (!audioMarkersFromStart.isSelected()) 130 audioMarkersFromStart.setSelected(false); 131 } 132 }); 133 audioMarkersFromStart.setSelected(Main.pref.getBoolean("marker.audiofromstart")); 134 audioMarkersFromStart.setToolTipText(tr("Automatically create audio markers from trackpoints (rather than explicit waypoints) with names or descriptions.")); 135 gui.audio.add(audioMarkersFromStart, GBC.eol().insets(10,0,0,0)); 113 136 114 137 audioForwardBackAmount.setText(Main.pref.get("audio.forwardbackamount", "10")); … … 139 162 Main.pref.put("marker.traceaudio", markerAudioTraceVisible.isSelected()); 140 163 Main.pref.put("marker.buttonlabels", markerButtonLabels.isSelected()); 141 Main.pref.put("marker.namedtrackpoints", markersNamedTrackpoints.isSelected());142 164 Main.pref.put("marker.makeautomarkers", makeAutoMarkers.isSelected()); 143 165 Main.pref.put("marker.audiofromexplicitwaypoints", audioMarkersFromExplicitWaypoints.isSelected()); 166 Main.pref.put("marker.audiofromuntimedwaypoints", audioMarkersFromUntimedWaypoints.isSelected()); 167 Main.pref.put("marker.audiofromnamedtrackpoints", audioMarkersFromNamedTrackpoints.isSelected()); 168 Main.pref.put("marker.audiofromstart", audioMarkersFromStart.isSelected()); 144 169 Main.pref.put("audio.forwardbackamount", audioForwardBackAmount.getText()); 145 170 Main.pref.put("audio.fastfwdmultiplier", audioFastForwardMultiplier.getText());
Note:
See TracChangeset
for help on using the changeset viewer.