1 | package org.openstreetmap.josm.io;
|
---|
2 |
|
---|
3 | import java.io.IOException;
|
---|
4 | import java.io.Reader;
|
---|
5 |
|
---|
6 | import org.jdom.Element;
|
---|
7 | import org.jdom.JDOMException;
|
---|
8 | import org.jdom.Namespace;
|
---|
9 | import org.jdom.input.SAXBuilder;
|
---|
10 | import org.openstreetmap.josm.data.GeoPoint;
|
---|
11 | import org.openstreetmap.josm.data.osm.DataSet;
|
---|
12 | import org.openstreetmap.josm.data.osm.LineSegment;
|
---|
13 | import org.openstreetmap.josm.data.osm.Node;
|
---|
14 | import org.openstreetmap.josm.data.osm.Track;
|
---|
15 | import org.openstreetmap.josm.gui.Main;
|
---|
16 |
|
---|
17 | /**
|
---|
18 | * Reads an gpx stream and construct a DataSet out of it. Some information may not be
|
---|
19 | * imported, since JOSM does not fully support GPX.
|
---|
20 | *
|
---|
21 | * @author imi
|
---|
22 | */
|
---|
23 | public class GpxReader {
|
---|
24 |
|
---|
25 | public static final Namespace XSD = Namespace.getNamespace("http://www.w3.org/2001/XMLSchema");
|
---|
26 | public static final Namespace GPX = Namespace.getNamespace("http://www.topografix.com/GPX/1/0");
|
---|
27 |
|
---|
28 | /**
|
---|
29 | * Read the input stream and return a DataSet from the stream.
|
---|
30 | *
|
---|
31 | * @param in
|
---|
32 | * @throws IOException An error with the provided stream occoured.
|
---|
33 | * @throws JDOMException An parse error occoured.
|
---|
34 | */
|
---|
35 | public DataSet parse(Reader in) throws JDOMException, IOException {
|
---|
36 | try {
|
---|
37 | final SAXBuilder builder = new SAXBuilder();
|
---|
38 | Element root = builder.build(in).getRootElement();
|
---|
39 | return parseDataSet(root);
|
---|
40 | } catch (NullPointerException npe) {
|
---|
41 | throw new JDOMException("NullPointerException. Probably a tag name mismatch.", npe);
|
---|
42 | } catch (ClassCastException cce) {
|
---|
43 | throw new JDOMException("ClassCastException. Probably a tag does not contain the correct type.", cce);
|
---|
44 | }
|
---|
45 | }
|
---|
46 |
|
---|
47 |
|
---|
48 | /**
|
---|
49 | * Read one node (waypoint).
|
---|
50 | * @param e The element to parse
|
---|
51 | * @return The Waypoint read from the element
|
---|
52 | */
|
---|
53 | private Node parseWaypoint(Element e) {
|
---|
54 | Node data = new Node();
|
---|
55 | data.coor = new GeoPoint(
|
---|
56 | Float.parseFloat(e.getAttributeValue("lat")),
|
---|
57 | Float.parseFloat(e.getAttributeValue("lon")));
|
---|
58 | return data;
|
---|
59 | }
|
---|
60 |
|
---|
61 | /**
|
---|
62 | * Read a data set from the element.
|
---|
63 | * @param e The element to parse
|
---|
64 | * @return The DataSet read from the element
|
---|
65 | */
|
---|
66 | private DataSet parseDataSet(Element e) {
|
---|
67 | DataSet data = new DataSet();
|
---|
68 | // read waypoints not contained in tracks or areas
|
---|
69 | for (Object o : e.getChildren("wpt", GPX))
|
---|
70 | addNode(data, parseWaypoint((Element)o));
|
---|
71 |
|
---|
72 | // read tracks
|
---|
73 | for (Object trackElement : e.getChildren("trk", GPX)) {
|
---|
74 | Track track = new Track();
|
---|
75 | for (Object trackSegmentElement : ((Element)trackElement).getChildren("trkseg", GPX)) {
|
---|
76 | Node start = null;
|
---|
77 | for (Object w : ((Element)trackSegmentElement).getChildren("trkpt", GPX)) {
|
---|
78 | Node node = parseWaypoint((Element)w);
|
---|
79 | node = addNode(data, node);
|
---|
80 | if (start == null)
|
---|
81 | start = node;
|
---|
82 | else {
|
---|
83 | LineSegment lineSegment = new LineSegment(start, node);
|
---|
84 | track.add(lineSegment);
|
---|
85 | start = null;
|
---|
86 | }
|
---|
87 | }
|
---|
88 | }
|
---|
89 | data.addTrack(track);
|
---|
90 | }
|
---|
91 |
|
---|
92 | return data;
|
---|
93 | }
|
---|
94 |
|
---|
95 | /**
|
---|
96 | * Adds the node to allNodes if it is not already listed. Does respect the
|
---|
97 | * preference setting "mergeNodes". Return the node in the list that correspond
|
---|
98 | * to the node in the list (either the new added or the old found).
|
---|
99 | *
|
---|
100 | * @param data The DataSet to add the node to.
|
---|
101 | * @param node The node that should be added.
|
---|
102 | * @return Either the parameter node or the old node found in the dataset.
|
---|
103 | */
|
---|
104 | private Node addNode (DataSet data, Node node) {
|
---|
105 | if (Main.pref.mergeNodes)
|
---|
106 | for (Node n : data.nodes)
|
---|
107 | if (node.equals(n))
|
---|
108 | return n;
|
---|
109 | data.nodes.add(node);
|
---|
110 | return node;
|
---|
111 | }
|
---|
112 | }
|
---|