// License: GPL. For details, see LICENSE file.
package public_transport;
import static org.openstreetmap.josm.tools.I18n.tr;
import java.util.Iterator;
import javax.swing.JOptionPane;
import javax.swing.event.TableModelEvent;
import javax.swing.event.TableModelListener;
import org.openstreetmap.josm.Main;
import org.openstreetmap.josm.command.ChangeCommand;
import org.openstreetmap.josm.command.Command;
import org.openstreetmap.josm.data.coor.LatLon;
import org.openstreetmap.josm.data.gpx.GpxTrack;
import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
import org.openstreetmap.josm.data.gpx.WayPoint;
import org.openstreetmap.josm.data.osm.Node;
public class TrackReference implements Comparable<TrackReference>, TableModelListener {
public GpxTrack track;
public TrackStoplistTableModel stoplistTM;
public String stopwatchStart;
public String gpsStartTime;
public String gpsSyncTime;
public double timeWindow;
public double threshold;
private StopImporterAction controller = null;
public boolean inEvent = false;
public TrackReference(GpxTrack track, StopImporterAction controller) {
this.track = track;
this.stoplistTM = new TrackStoplistTableModel(this);
this.stopwatchStart = "00:00:00";
this.gpsStartTime = null;
this.gpsSyncTime = null;
this.controller = controller;
if (track != null) {
Iterator<GpxTrackSegment> siter = track.getSegments().iterator();
while ((siter.hasNext()) && (this.gpsSyncTime == null)) {
Iterator<WayPoint> witer = siter.next().getWayPoints().iterator();
if (witer.hasNext()) {
this.gpsStartTime = witer.next().getString("time");
if (this.gpsStartTime != null)
this.gpsSyncTime = this.gpsStartTime.substring(11, 19);
}
}
if (this.gpsSyncTime == null) {
JOptionPane.showMessageDialog(null,
tr("The GPX file doesn''t contain valid trackpoints. "
+ "Please use a GPX file that has trackpoints."),
tr("GPX File Trouble"), JOptionPane.ERROR_MESSAGE);
this.gpsStartTime = "1970-01-01T00:00:00Z";
this.gpsSyncTime = this.stopwatchStart;
}
} else
this.gpsSyncTime = this.stopwatchStart;
this.timeWindow = 20;
this.threshold = 20;
}
public GpxTrack getGpxTrack() {
return track;
}
@Override
public int compareTo(TrackReference tr) {
String name = (String) track.getAttributes().get("name");
String tr_name = (String) tr.track.getAttributes().get("name");
if (name != null) {
if (tr_name == null)
return -1;
return name.compareTo(tr_name);
}
return 1;
}
@Override
public String toString() {
String buf = (String) track.getAttributes().get("name");
if (buf == null)
return tr("unnamed");
return buf;
}
@Override
public void tableChanged(TableModelEvent e) {
if ((e.getType() == TableModelEvent.UPDATE) && (e.getFirstRow() >= 0)) {
if (inEvent)
return;
double time = StopImporterDialog
.parseTime((String) stoplistTM.getValueAt(e.getFirstRow(), 0));
if (time < 0) {
stoplistTM.setValueAt(stoplistTM.timeAt(e.getFirstRow()), e.getFirstRow(), 0);
JOptionPane.showMessageDialog(null, tr("Can''t parse a time from this string."),
tr("Invalid value"), JOptionPane.ERROR_MESSAGE);
return;
}
Main.main.undoRedo.add(new TrackStoplistNameCommand(this, e.getFirstRow()));
stoplistTM.setTimeAt(e.getFirstRow(),
(String) stoplistTM.getValueAt(e.getFirstRow(), 0));
}
}
public LatLon computeCoor(double time) {
double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
if (gpsSyncTime < dGpsStartTime - 12 * 60 * 60)
gpsSyncTime += 24 * 60 * 60;
double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
time += timeDelta;
WayPoint wayPoint = null;
WayPoint lastWayPoint = null;
double wayPointTime = 0;
double lastWayPointTime = 0;
Iterator<GpxTrackSegment> siter = track.getSegments().iterator();
while (siter.hasNext()) {
Iterator<WayPoint> witer = siter.next().getWayPoints().iterator();
while (witer.hasNext()) {
wayPoint = witer.next();
String startTime = wayPoint.getString("time");
wayPointTime = StopImporterDialog.parseTime(startTime.substring(11, 19));
if (startTime.substring(11, 19).compareTo(gpsStartTime.substring(11, 19)) == -1)
wayPointTime += 24 * 60 * 60;
if (wayPointTime >= time)
break;
lastWayPoint = wayPoint;
lastWayPointTime = wayPointTime;
}
if (wayPointTime >= time)
break;
}
double lat = 0;
if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
lat = wayPoint.getCoor().lat();
else
lat = wayPoint.getCoor().lat() * (time - lastWayPointTime)
/ (wayPointTime - lastWayPointTime)
+ lastWayPoint.getCoor().lat() * (wayPointTime - time)
/ (wayPointTime - lastWayPointTime);
double lon = 0;
if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
lon = wayPoint.getCoor().lon();
else
lon = wayPoint.getCoor().lon() * (time - lastWayPointTime)
/ (wayPointTime - lastWayPointTime)
+ lastWayPoint.getCoor().lon() * (wayPointTime - time)
/ (wayPointTime - lastWayPointTime);
return new LatLon(lat, lon);
}
public void relocateNodes() {
for (int i = 0; i < stoplistTM.getNodes().size(); ++i) {
Node node = stoplistTM.nodeAt(i);
if (node == null)
continue;
double time = StopImporterDialog.parseTime((String) stoplistTM.getValueAt(i, 0));
LatLon latLon = computeCoor(time);
Node newNode = new Node(node);
newNode.setCoor(latLon);
Command cmd = new ChangeCommand(node, newNode);
if (cmd != null) {
Main.main.undoRedo.add(cmd);
}
}
}
}