// License: GPL. For details, see LICENSE file. package public_transport; import static org.openstreetmap.josm.tools.I18n.tr; import java.util.Collection; import java.util.Iterator; import java.util.Vector; import org.openstreetmap.josm.Main; import org.openstreetmap.josm.command.Command; import org.openstreetmap.josm.data.coor.LatLon; import org.openstreetmap.josm.data.gpx.GpxTrackSegment; import org.openstreetmap.josm.data.gpx.WayPoint; import org.openstreetmap.josm.data.osm.Node; import org.openstreetmap.josm.data.osm.OsmPrimitive; public class TrackSuggestStopsCommand extends Command { private TrackStoplistTableModel stoplistTM = null; private String type = null; private String stopwatchStart; private String gpsStartTime; private String gpsSyncTime; private double timeWindow; private double threshold; private Collection<GpxTrackSegment> segments = null; private Vector<Vector<Object>> tableDataModel = null; private Vector<Node> nodes = null; private Vector<String> times = null; public TrackSuggestStopsCommand(StopImporterAction controller) { if (controller.getCurrentTrack() == null) return; stoplistTM = controller.getCurrentTrack().stoplistTM; type = controller.getDialog().getStoptype(); stopwatchStart = controller.getCurrentTrack().stopwatchStart; gpsStartTime = controller.getCurrentTrack().gpsStartTime; gpsSyncTime = controller.getCurrentTrack().gpsSyncTime; timeWindow = controller.getCurrentTrack().timeWindow; threshold = controller.getCurrentTrack().threshold; segments = controller.getCurrentTrack().getGpxTrack().getSegments(); } @Override @SuppressWarnings("unchecked") public boolean executeCommand() { if (stoplistTM == null) return false; tableDataModel = (Vector<Vector<Object>>) stoplistTM.getDataVector().clone(); nodes = (Vector<Node>) stoplistTM.getNodes().clone(); times = (Vector<String>) stoplistTM.getTimes().clone(); for (int i = 0; i < stoplistTM.getNodes().size(); ++i) { Node node = stoplistTM.nodeAt(i); if (node == null) continue; Main.getLayerManager().getEditDataSet().removePrimitive(node); node.setDeleted(true); } stoplistTM.clear(); Vector<WayPoint> wayPoints = new Vector<>(); Iterator<GpxTrackSegment> siter = segments.iterator(); while (siter.hasNext()) { Iterator<WayPoint> witer = siter.next().getWayPoints().iterator(); while (witer.hasNext()) { wayPoints.add(witer.next()); } } Vector<Double> wayPointsDist = new Vector<>(wayPoints.size()); int i = 0; double time = -48 * 60 * 60; double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime); while ((i < wayPoints.size()) && (time < dGpsStartTime + timeWindow / 2)) { if (wayPoints.elementAt(i).getString("time") != null) time = StopImporterDialog .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19)); if (time < dGpsStartTime) time += 24 * 60 * 60; wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY)); ++i; } while (i < wayPoints.size()) { int j = i; double time2 = time; while ((j > 0) && (time - timeWindow / 2 < time2)) { --j; if (wayPoints.elementAt(j).getString("time") != null) time2 = StopImporterDialog .parseTime(wayPoints.elementAt(j).getString("time").substring(11, 19)); if (time2 < dGpsStartTime) time2 += 24 * 60 * 60; } int k = i + 1; time2 = time; while ((k < wayPoints.size()) && (time + timeWindow / 2 > time2)) { if (wayPoints.elementAt(k).getString("time") != null) time2 = StopImporterDialog .parseTime(wayPoints.elementAt(k).getString("time").substring(11, 19)); if (time2 < dGpsStartTime) time2 += 24 * 60 * 60; ++k; } if (j < k) { double dist = 0; LatLon latLonI = wayPoints.elementAt(i).getCoor(); for (int l = j; l < k; ++l) { double distL = latLonI.greatCircleDistance(wayPoints.elementAt(l).getCoor()); if (distL > dist) dist = distL; } wayPointsDist.add(Double.valueOf(dist)); } else wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY)); if (wayPoints.elementAt(i).getString("time") != null) time = StopImporterDialog .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19)); if (time < dGpsStartTime) time += 24 * 60 * 60; ++i; } LatLon lastStopCoor = null; for (i = 1; i < wayPoints.size() - 1; ++i) { if (wayPointsDist.elementAt(i).doubleValue() >= threshold) continue; if ((wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i - 1)) != -1) || (wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i + 1)) != -1)) continue; LatLon latLon = wayPoints.elementAt(i).getCoor(); if ((lastStopCoor != null) && (lastStopCoor.greatCircleDistance(latLon) < threshold)) continue; if (wayPoints.elementAt(i).getString("time") != null) { time = StopImporterDialog .parseTime(wayPoints.elementAt(i).getString("time").substring(11, 19)); double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime); if (gpsSyncTime < dGpsStartTime - 12 * 60 * 60) gpsSyncTime += 24 * 60 * 60; double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart); time -= timeDelta; Node node = StopImporterAction.createNode(latLon, type, ""); stoplistTM.insertRow(-1, node, StopImporterAction.timeOf(time), "", new TransText(null)); } lastStopCoor = latLon; } return true; } @Override public void undoCommand() { if (stoplistTM == null) return; for (int i = 0; i < stoplistTM.getNodes().size(); ++i) { Node node = stoplistTM.nodeAt(i); if (node == null) continue; Main.getLayerManager().getEditDataSet().removePrimitive(node); node.setDeleted(true); } stoplistTM.setDataVector(tableDataModel); stoplistTM.setNodes(nodes); stoplistTM.setTimes(times); for (int i = 0; i < stoplistTM.getNodes().size(); ++i) { Node node = stoplistTM.nodeAt(i); if (node == null) continue; node.setDeleted(false); Main.getLayerManager().getEditDataSet().addPrimitive(node); } } @Override public void fillModifiedData(Collection<OsmPrimitive> modified, Collection<OsmPrimitive> deleted, Collection<OsmPrimitive> added) { } @Override public String getDescriptionText() { return tr("Public Transport: Suggest stops"); } /* private class NodeSortEntry implements Comparable<NodeSortEntry> { public Node node = null; public String time = null; public String name = null; public double startTime = 0; public NodeSortEntry(Node node, String time, String name, double startTime) { this.node = node; this.time = time; this.name = name; } @Override public int compareTo(NodeSortEntry nse) { double time = StopImporterDialog.parseTime(this.time); if (time - startTime > 12 * 60 * 60) time -= 24 * 60 * 60; double nseTime = StopImporterDialog.parseTime(nse.time); if (nseTime - startTime > 12 * 60 * 60) nseTime -= 24 * 60 * 60; if (time < nseTime) return -1; else if (time > nseTime) return 1; else return 0; } }*/ }