1 | package public_transport;
|
---|
2 |
|
---|
3 | import static org.openstreetmap.josm.tools.I18n.marktr;
|
---|
4 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
5 |
|
---|
6 | import java.util.Iterator;
|
---|
7 | import java.util.Vector;
|
---|
8 | import javax.swing.JOptionPane;
|
---|
9 | import javax.swing.event.TableModelEvent;
|
---|
10 | import javax.swing.event.TableModelListener;
|
---|
11 |
|
---|
12 | import org.openstreetmap.josm.Main;
|
---|
13 | import org.openstreetmap.josm.command.Command;
|
---|
14 | import org.openstreetmap.josm.command.ChangeCommand;
|
---|
15 | import org.openstreetmap.josm.command.DeleteCommand;
|
---|
16 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
17 | import org.openstreetmap.josm.data.gpx.GpxTrack;
|
---|
18 | import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
|
---|
19 | import org.openstreetmap.josm.data.gpx.WayPoint;
|
---|
20 | import org.openstreetmap.josm.data.osm.Node;
|
---|
21 |
|
---|
22 | public class TrackReference
|
---|
23 | implements Comparable< TrackReference >, TableModelListener
|
---|
24 | {
|
---|
25 | public GpxTrack track;
|
---|
26 | public TrackStoplistTableModel stoplistTM;
|
---|
27 | public String stopwatchStart;
|
---|
28 | public String gpsStartTime;
|
---|
29 | public String gpsSyncTime;
|
---|
30 | public double timeWindow;
|
---|
31 | public double threshold;
|
---|
32 | private StopImporterAction controller = null;
|
---|
33 |
|
---|
34 | public TrackReference(GpxTrack track, StopImporterAction controller)
|
---|
35 | {
|
---|
36 | this.track = track;
|
---|
37 | this.stoplistTM = new TrackStoplistTableModel(this);
|
---|
38 | this.stopwatchStart = "00:00:00";
|
---|
39 | this.gpsStartTime = null;
|
---|
40 | this.gpsSyncTime = null;
|
---|
41 | this.controller = controller;
|
---|
42 | if (track != null)
|
---|
43 | {
|
---|
44 | Iterator< GpxTrackSegment > siter = track.getSegments().iterator();
|
---|
45 | while ((siter.hasNext()) && (this.gpsSyncTime == null))
|
---|
46 | {
|
---|
47 | Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
|
---|
48 | if (witer.hasNext())
|
---|
49 | {
|
---|
50 | this.gpsStartTime = witer.next().getString("time");
|
---|
51 | if (this.gpsStartTime != null)
|
---|
52 | this.gpsSyncTime = this.gpsStartTime.substring(11, 19);
|
---|
53 | }
|
---|
54 | }
|
---|
55 | if (this.gpsSyncTime == null)
|
---|
56 | {
|
---|
57 | JOptionPane.showMessageDialog
|
---|
58 | (null, "The GPX file doesn't contain valid trackpoints. "
|
---|
59 | + "Please use a GPX file that has trackpoints.", "GPX File Trouble",
|
---|
60 | JOptionPane.ERROR_MESSAGE);
|
---|
61 |
|
---|
62 | this.gpsStartTime = "1970-01-01T00:00:00Z";
|
---|
63 | this.gpsSyncTime = this.stopwatchStart;
|
---|
64 | }
|
---|
65 | }
|
---|
66 | else
|
---|
67 | this.gpsSyncTime = this.stopwatchStart;
|
---|
68 | this.timeWindow = 20;
|
---|
69 | this.threshold = 20;
|
---|
70 | }
|
---|
71 |
|
---|
72 | public int compareTo(TrackReference tr)
|
---|
73 | {
|
---|
74 | String name = (String)track.getAttributes().get("name");
|
---|
75 | String tr_name = (String)tr.track.getAttributes().get("name");
|
---|
76 | if (name != null)
|
---|
77 | {
|
---|
78 | if (tr_name == null)
|
---|
79 | return -1;
|
---|
80 | return name.compareTo(tr_name);
|
---|
81 | }
|
---|
82 | return 1;
|
---|
83 | }
|
---|
84 |
|
---|
85 | public String toString()
|
---|
86 | {
|
---|
87 | String buf = (String)track.getAttributes().get("name");
|
---|
88 | if (buf == null)
|
---|
89 | return "unnamed";
|
---|
90 | return buf;
|
---|
91 | }
|
---|
92 |
|
---|
93 | public void tableChanged(TableModelEvent e)
|
---|
94 | {
|
---|
95 | if ((e.getType() == TableModelEvent.UPDATE) && (e.getFirstRow() >= 0))
|
---|
96 | {
|
---|
97 | double time = StopImporterDialog.parseTime
|
---|
98 | ((String)stoplistTM.getValueAt(e.getFirstRow(), 0));
|
---|
99 | if (time < 0)
|
---|
100 | {
|
---|
101 | JOptionPane.showMessageDialog
|
---|
102 | (null, "Can't parse a time from this string.", "Invalid value",
|
---|
103 | JOptionPane.ERROR_MESSAGE);
|
---|
104 | return;
|
---|
105 | }
|
---|
106 |
|
---|
107 | LatLon latLon = computeCoor(time);
|
---|
108 |
|
---|
109 | if (stoplistTM.nodes.elementAt(e.getFirstRow()) == null)
|
---|
110 | {
|
---|
111 | Node node = controller.createNode
|
---|
112 | (latLon, (String)stoplistTM.getValueAt(e.getFirstRow(), 1));
|
---|
113 | stoplistTM.nodes.set(e.getFirstRow(), node);
|
---|
114 | }
|
---|
115 | else
|
---|
116 | {
|
---|
117 | Node node = new Node(stoplistTM.nodes.elementAt(e.getFirstRow()));
|
---|
118 | node.setCoor(latLon);
|
---|
119 | node.put("name", (String)stoplistTM.getValueAt(e.getFirstRow(), 1));
|
---|
120 | Command cmd = new ChangeCommand(stoplistTM.nodes.elementAt(e.getFirstRow()), node);
|
---|
121 | if (cmd != null) {
|
---|
122 | Main.main.undoRedo.add(cmd);
|
---|
123 | }
|
---|
124 | }
|
---|
125 | }
|
---|
126 | }
|
---|
127 |
|
---|
128 | public LatLon computeCoor(double time)
|
---|
129 | {
|
---|
130 | double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
|
---|
131 | double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
|
---|
132 | if (gpsSyncTime < dGpsStartTime - 12*60*60)
|
---|
133 | gpsSyncTime += 24*60*60;
|
---|
134 | double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
|
---|
135 | time += timeDelta;
|
---|
136 |
|
---|
137 | WayPoint wayPoint = null;
|
---|
138 | WayPoint lastWayPoint = null;
|
---|
139 | double wayPointTime = 0;
|
---|
140 | double lastWayPointTime = 0;
|
---|
141 | Iterator< GpxTrackSegment > siter = track.getSegments().iterator();
|
---|
142 | while (siter.hasNext())
|
---|
143 | {
|
---|
144 | Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
|
---|
145 | while (witer.hasNext())
|
---|
146 | {
|
---|
147 | wayPoint = witer.next();
|
---|
148 | String startTime = wayPoint.getString("time");
|
---|
149 | wayPointTime = StopImporterDialog.parseTime(startTime.substring(11, 19));
|
---|
150 | if (startTime.substring(11, 19).compareTo(gpsStartTime.substring(11, 19)) == -1)
|
---|
151 | wayPointTime += 24*60*60;
|
---|
152 | if (wayPointTime >= time)
|
---|
153 | break;
|
---|
154 | lastWayPoint = wayPoint;
|
---|
155 | lastWayPointTime = wayPointTime;
|
---|
156 | }
|
---|
157 | if (wayPointTime >= time)
|
---|
158 | break;
|
---|
159 | }
|
---|
160 |
|
---|
161 | double lat = 0;
|
---|
162 | if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
|
---|
163 | lat = wayPoint.getCoor().lat();
|
---|
164 | else
|
---|
165 | lat = wayPoint.getCoor().lat()
|
---|
166 | *(time - lastWayPointTime)/(wayPointTime - lastWayPointTime)
|
---|
167 | + lastWayPoint.getCoor().lat()
|
---|
168 | *(wayPointTime - time)/(wayPointTime - lastWayPointTime);
|
---|
169 | double lon = 0;
|
---|
170 | if ((wayPointTime == lastWayPointTime) || (lastWayPoint == null))
|
---|
171 | lon = wayPoint.getCoor().lon();
|
---|
172 | else
|
---|
173 | lon = wayPoint.getCoor().lon()
|
---|
174 | *(time - lastWayPointTime)/(wayPointTime - lastWayPointTime)
|
---|
175 | + lastWayPoint.getCoor().lon()
|
---|
176 | *(wayPointTime - time)/(wayPointTime - lastWayPointTime);
|
---|
177 |
|
---|
178 | return new LatLon(lat, lon);
|
---|
179 | }
|
---|
180 |
|
---|
181 | public void relocateNodes()
|
---|
182 | {
|
---|
183 | for (int i = 0; i < stoplistTM.nodes.size(); ++i)
|
---|
184 | {
|
---|
185 | Node node = stoplistTM.nodes.elementAt(i);
|
---|
186 | if (node == null)
|
---|
187 | continue;
|
---|
188 |
|
---|
189 | double time = StopImporterDialog.parseTime
|
---|
190 | ((String)stoplistTM.getValueAt(i, 0));
|
---|
191 | LatLon latLon = computeCoor(time);
|
---|
192 |
|
---|
193 | Node newNode = new Node(node);
|
---|
194 | newNode.setCoor(latLon);
|
---|
195 | Command cmd = new ChangeCommand(node, newNode);
|
---|
196 | if (cmd != null)
|
---|
197 | {
|
---|
198 | Main.main.undoRedo.add(cmd);
|
---|
199 | }
|
---|
200 | }
|
---|
201 | }
|
---|
202 |
|
---|
203 | public void suggestStops()
|
---|
204 | {
|
---|
205 | Vector< WayPoint > wayPoints = new Vector< WayPoint >();
|
---|
206 | Iterator< GpxTrackSegment > siter = track.getSegments().iterator();
|
---|
207 | while (siter.hasNext())
|
---|
208 | {
|
---|
209 | Iterator< WayPoint > witer = siter.next().getWayPoints().iterator();
|
---|
210 | while (witer.hasNext())
|
---|
211 | wayPoints.add(witer.next());
|
---|
212 | }
|
---|
213 | Vector< Double > wayPointsDist = new Vector< Double >(wayPoints.size());
|
---|
214 |
|
---|
215 | int i = 0;
|
---|
216 | double time = -48*60*60;
|
---|
217 | double dGpsStartTime = StopImporterDialog.parseTime(gpsStartTime);
|
---|
218 | while ((i < wayPoints.size()) && (time < dGpsStartTime + timeWindow/2))
|
---|
219 | {
|
---|
220 | if (wayPoints.elementAt(i).getString("time") != null)
|
---|
221 | time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
|
---|
222 | .getString("time").substring(11,19));
|
---|
223 | if (time < dGpsStartTime)
|
---|
224 | time += 24*60*60;
|
---|
225 | wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
|
---|
226 | ++i;
|
---|
227 | }
|
---|
228 | while (i < wayPoints.size())
|
---|
229 | {
|
---|
230 | int j = i;
|
---|
231 | double time2 = time;
|
---|
232 | while ((j > 0) && (time - timeWindow/2 < time2))
|
---|
233 | {
|
---|
234 | --j;
|
---|
235 | if (wayPoints.elementAt(j).getString("time") != null)
|
---|
236 | time2 = StopImporterDialog.parseTime(wayPoints.elementAt(j)
|
---|
237 | .getString("time").substring(11,19));
|
---|
238 | if (time2 < dGpsStartTime)
|
---|
239 | time2 += 24*60*60;
|
---|
240 | }
|
---|
241 | int k = i + 1;
|
---|
242 | time2 = time;
|
---|
243 | while ((k < wayPoints.size()) && (time + timeWindow/2 > time2))
|
---|
244 | {
|
---|
245 | if (wayPoints.elementAt(k).getString("time") != null)
|
---|
246 | time2 = StopImporterDialog.parseTime(wayPoints.elementAt(k)
|
---|
247 | .getString("time").substring(11,19));
|
---|
248 | if (time2 < dGpsStartTime)
|
---|
249 | time2 += 24*60*60;
|
---|
250 | ++k;
|
---|
251 | }
|
---|
252 |
|
---|
253 | if (j < k)
|
---|
254 | {
|
---|
255 | double dist = 0;
|
---|
256 | LatLon latLonI = wayPoints.elementAt(i).getCoor();
|
---|
257 | for (int l = j; l < k; ++l)
|
---|
258 | {
|
---|
259 | double distL = latLonI.greatCircleDistance(wayPoints.elementAt(l).getCoor());
|
---|
260 | if (distL > dist)
|
---|
261 | dist = distL;
|
---|
262 | }
|
---|
263 | wayPointsDist.add(Double.valueOf(dist));
|
---|
264 | }
|
---|
265 | else
|
---|
266 | wayPointsDist.add(Double.valueOf(Double.POSITIVE_INFINITY));
|
---|
267 |
|
---|
268 | if (wayPoints.elementAt(i).getString("time") != null)
|
---|
269 | time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
|
---|
270 | .getString("time").substring(11,19));
|
---|
271 | if (time < dGpsStartTime)
|
---|
272 | time += 24*60*60;
|
---|
273 | ++i;
|
---|
274 | }
|
---|
275 |
|
---|
276 | Vector< Node > toDelete = new Vector< Node >();
|
---|
277 | for (i = 0; i < stoplistTM.getRowCount(); ++i)
|
---|
278 | {
|
---|
279 | if ((Node)stoplistTM.nodes.elementAt(i) != null)
|
---|
280 | toDelete.add((Node)stoplistTM.nodes.elementAt(i));
|
---|
281 | }
|
---|
282 | if (!toDelete.isEmpty())
|
---|
283 | {
|
---|
284 | Command cmd = DeleteCommand.delete
|
---|
285 | (Main.main.getEditLayer(), toDelete);
|
---|
286 | if (cmd == null)
|
---|
287 | return;
|
---|
288 | Main.main.undoRedo.add(cmd);
|
---|
289 | }
|
---|
290 | stoplistTM.clear();
|
---|
291 |
|
---|
292 | LatLon lastStopCoor = null;
|
---|
293 | for (i = 1; i < wayPoints.size()-1; ++i)
|
---|
294 | {
|
---|
295 | if (wayPointsDist.elementAt(i).doubleValue() >= threshold)
|
---|
296 | continue;
|
---|
297 | if ((wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i-1)) != -1)
|
---|
298 | || (wayPointsDist.elementAt(i).compareTo(wayPointsDist.elementAt(i+1)) != -1))
|
---|
299 | continue;
|
---|
300 |
|
---|
301 | LatLon latLon = wayPoints.elementAt(i).getCoor();
|
---|
302 | if ((lastStopCoor != null) && (lastStopCoor.greatCircleDistance(latLon) < threshold))
|
---|
303 | continue;
|
---|
304 |
|
---|
305 | if (wayPoints.elementAt(i).getString("time") != null)
|
---|
306 | {
|
---|
307 | time = StopImporterDialog.parseTime(wayPoints.elementAt(i)
|
---|
308 | .getString("time").substring(11,19));
|
---|
309 | double gpsSyncTime = StopImporterDialog.parseTime(this.gpsSyncTime);
|
---|
310 | if (gpsSyncTime < dGpsStartTime - 12*60*60)
|
---|
311 | gpsSyncTime += 24*60*60;
|
---|
312 | double timeDelta = gpsSyncTime - StopImporterDialog.parseTime(stopwatchStart);
|
---|
313 | time -= timeDelta;
|
---|
314 | stoplistTM.insertRow(-1, StopImporterAction.timeOf(time));
|
---|
315 | Node node = controller.createNode(latLon, "");
|
---|
316 | stoplistTM.nodes.set(stoplistTM.getRowCount()-1, node);
|
---|
317 | }
|
---|
318 |
|
---|
319 | lastStopCoor = latLon;
|
---|
320 | }
|
---|
321 | }
|
---|
322 | };
|
---|