1 | package org.openstreetmap.josm.io;
|
---|
2 |
|
---|
3 | import static org.openstreetmap.josm.tools.I18n.tr;
|
---|
4 |
|
---|
5 | import java.io.IOException;
|
---|
6 | import java.io.InputStream;
|
---|
7 | import java.io.InputStreamReader;
|
---|
8 | import java.util.ArrayList;
|
---|
9 | import java.util.Collection;
|
---|
10 | import java.util.LinkedList;
|
---|
11 | import java.util.Stack;
|
---|
12 |
|
---|
13 | import org.openstreetmap.josm.data.coor.LatLon;
|
---|
14 | import org.openstreetmap.josm.gui.layer.MarkerLayer.Marker;
|
---|
15 | import org.openstreetmap.josm.gui.layer.RawGpsLayer.GpsPoint;
|
---|
16 | import org.xml.sax.Attributes;
|
---|
17 | import org.xml.sax.SAXException;
|
---|
18 |
|
---|
19 | import uk.co.wilson.xml.MinML2;
|
---|
20 |
|
---|
21 | /**
|
---|
22 | * Read raw gps data from a gpx file. Only way points with their ways segments
|
---|
23 | * and waypoints are imported.
|
---|
24 | * @author imi
|
---|
25 | */
|
---|
26 | public class RawGpsReader {
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * Hold the resulting gps data (tracks and their track points)
|
---|
30 | */
|
---|
31 | public Collection<Collection<GpsPoint>> trackData = new LinkedList<Collection<GpsPoint>>();
|
---|
32 |
|
---|
33 | /**
|
---|
34 | * Hold the waypoints of the gps data.
|
---|
35 | */
|
---|
36 | public Collection<Marker> markerData = new ArrayList<Marker>();
|
---|
37 |
|
---|
38 | private class Parser extends MinML2 {
|
---|
39 | /**
|
---|
40 | * Current track to be read. The last entry is the current trkpt.
|
---|
41 | * If in wpt-mode, it contain only one GpsPoint.
|
---|
42 | */
|
---|
43 | private Collection<GpsPoint> current = new LinkedList<GpsPoint>();
|
---|
44 | private LatLon currentLatLon;
|
---|
45 | private String currentTime = "";
|
---|
46 | private String currentName = "";
|
---|
47 | private Stack<String> tags = new Stack<String>();
|
---|
48 |
|
---|
49 | @Override public void startElement(String namespaceURI, String localName, String qName, Attributes atts) throws SAXException {
|
---|
50 | if (qName.equals("wpt") || qName.equals("trkpt")) {
|
---|
51 | try {
|
---|
52 | double lat = Double.parseDouble(atts.getValue("lat"));
|
---|
53 | double lon = Double.parseDouble(atts.getValue("lon"));
|
---|
54 | if (Math.abs(lat) > 90)
|
---|
55 | throw new SAXException(tr("Data error: lat value \"{0}\" is out of bound.", lat));
|
---|
56 | if (Math.abs(lon) > 180)
|
---|
57 | throw new SAXException(tr("Data error: lon value \"{0}\" is out of bound.", lon));
|
---|
58 | currentLatLon = new LatLon(lat, lon);
|
---|
59 | } catch (NumberFormatException e) {
|
---|
60 | e.printStackTrace();
|
---|
61 | throw new SAXException(e);
|
---|
62 | }
|
---|
63 | currentTime = "";
|
---|
64 | currentName = "";
|
---|
65 | }
|
---|
66 | tags.push(qName);
|
---|
67 | }
|
---|
68 |
|
---|
69 | @Override public void characters(char[] ch, int start, int length) {
|
---|
70 | String peek = tags.peek();
|
---|
71 | if (peek.equals("time") || peek.equals("name")) {
|
---|
72 | String tag = tags.pop();
|
---|
73 | if (tags.empty() || (!tags.peek().equals("wpt") && !tags.peek().equals("trkpt"))) {
|
---|
74 | tags.push(tag);
|
---|
75 | return;
|
---|
76 | }
|
---|
77 | String contents = new String(ch, start, length);
|
---|
78 | if (peek.equals("time")) currentTime += contents; else currentName += contents;
|
---|
79 | tags.push(tag);
|
---|
80 | }
|
---|
81 | }
|
---|
82 |
|
---|
83 | @Override public void endElement(String namespaceURI, String localName, String qName) {
|
---|
84 | if (qName.equals("trkpt")) {
|
---|
85 | current.add(new GpsPoint(currentLatLon, currentTime));
|
---|
86 | currentTime = "";
|
---|
87 | currentName = "";
|
---|
88 | } else if (qName.equals("wpt")) {
|
---|
89 | markerData.add(new Marker(currentLatLon, currentName, null));
|
---|
90 | currentTime = "";
|
---|
91 | currentName = "";
|
---|
92 | } else if (qName.equals("trkseg") || qName.equals("trk") || qName.equals("gpx")) {
|
---|
93 | newTrack();
|
---|
94 | currentTime = "";
|
---|
95 | currentName = "";
|
---|
96 | }
|
---|
97 | tags.pop();
|
---|
98 | }
|
---|
99 |
|
---|
100 | private void newTrack() {
|
---|
101 | if (!current.isEmpty()) {
|
---|
102 | trackData.add(current);
|
---|
103 | current = new LinkedList<GpsPoint>();
|
---|
104 | }
|
---|
105 | }
|
---|
106 | }
|
---|
107 |
|
---|
108 |
|
---|
109 | /**
|
---|
110 | * Parse the input stream and store the result in trackData and markerData
|
---|
111 | */
|
---|
112 | public RawGpsReader(InputStream source) throws SAXException, IOException {
|
---|
113 | Parser parser = new Parser();
|
---|
114 | parser.parse(new InputStreamReader(source, "UTF-8"));
|
---|
115 | }
|
---|
116 | }
|
---|