source: josm/trunk/src/org/openstreetmap/josm/io/GpxWriter.java @ 5241

Revision 2907, 8.0 KB checked in by jttt, 2 years ago (diff)

Gpx refactoring - GpxTrack and GpxTrackSegment is now interface, implementations for specific use can be provided (currently JOSM supports immutable gpx track, livegps plugin supports append only track).

  • track length and bounds are precalculated
  • GpxLayer paints only currently visible segments
  • Property svn:eol-style set to native
Line 
1// License: GPL. Copyright 2007 by Immanuel Scholz and others
2package org.openstreetmap.josm.io;
3
4import static org.openstreetmap.josm.tools.I18n.tr;
5
6import java.io.BufferedWriter;
7import java.io.OutputStream;
8import java.io.OutputStreamWriter;
9import java.io.PrintWriter;
10import java.io.UnsupportedEncodingException;
11import java.util.Collection;
12import java.util.Map;
13
14import org.openstreetmap.josm.data.Bounds;
15import org.openstreetmap.josm.data.coor.LatLon;
16import org.openstreetmap.josm.data.gpx.GpxData;
17import org.openstreetmap.josm.data.gpx.GpxLink;
18import org.openstreetmap.josm.data.gpx.GpxRoute;
19import org.openstreetmap.josm.data.gpx.GpxTrack;
20import org.openstreetmap.josm.data.gpx.GpxTrackSegment;
21import org.openstreetmap.josm.data.gpx.WayPoint;
22
23/**
24 * Writes GPX files from GPX data or OSM data.
25 */
26public class GpxWriter extends XmlWriter {
27
28    public GpxWriter(PrintWriter out) {
29        super(out);
30    }
31
32    public GpxWriter(OutputStream out) throws UnsupportedEncodingException {
33        super(new PrintWriter(new BufferedWriter(new OutputStreamWriter(out, "UTF-8"))));
34    }
35
36    public GpxWriter() {
37        super(null);
38        //sorry for this one here, this will be cleaned up once the new scheme works
39    }
40
41    private GpxData data;
42    private String indent = "";
43
44    private final static int WAY_POINT = 0;
45    private final static int ROUTE_POINT = 1;
46    private final static int TRACK_POINT = 2;
47
48    public void write(GpxData data) {
49        this.data = data;
50        out.println("<?xml version='1.0' encoding='UTF-8'?>");
51        out.println("<gpx version=\"1.1\" creator=\"JOSM GPX export\" xmlns=\"http://www.topografix.com/GPX/1/1\"\n" +
52                "    xmlns:xsi=\"http://www.w3.org/2001/XMLSchema-instance\" \n" +
53        "    xsi:schemaLocation=\"http://www.topografix.com/GPX/1/1 http://www.topografix.com/GPX/1/1/gpx.xsd\">");
54        indent = "  ";
55        writeMetaData();
56        writeWayPoints();
57        writeRoutes();
58        writeTracks();
59        out.print("</gpx>");
60        out.flush();
61    }
62
63    @SuppressWarnings("unchecked")
64    private void writeAttr(Map<String, Object> attr) {
65        // FIXME this loop is evil, because it does not assure the
66        // correct element order specified by the xml schema.
67        // for now it works, but future extension could get very complex and unmaintainable
68        for (Map.Entry<String, Object> ent : attr.entrySet()) {
69            String k = ent.getKey();
70            if (k.equals(GpxData.META_LINKS)) {
71                for (GpxLink link : (Collection<GpxLink>) ent.getValue()) {
72                    gpxLink(link);
73                }
74            } else {
75                simpleTag(k, ent.getValue().toString());
76            }
77        }
78    }
79
80    @SuppressWarnings("unchecked")
81    private void writeMetaData() {
82        Map<String, Object> attr = data.attr;
83        openln("metadata");
84
85        // write the description
86        if (attr.containsKey(GpxData.META_DESC)) {
87            simpleTag("desc", (String)attr.get(GpxData.META_DESC));
88        }
89
90        // write the author details
91        if (attr.containsKey(GpxData.META_AUTHOR_NAME)
92                || attr.containsKey(GpxData.META_AUTHOR_EMAIL)) {
93            openln("author");
94            // write the name
95            simpleTag("name", (String) attr.get(GpxData.META_AUTHOR_NAME));
96            // write the email address
97            if(attr.containsKey(GpxData.META_AUTHOR_EMAIL)) {
98                String[] tmp = ((String)attr.get(GpxData.META_AUTHOR_EMAIL)).split("@");
99                if(tmp.length == 2) {
100                    inline("email", "id=\"" + tmp[0] + "\" domain=\""+tmp[1]+"\"");
101                }
102            }
103            // write the author link
104            gpxLink((GpxLink) attr.get(GpxData.META_AUTHOR_LINK));
105            closeln("author");
106        }
107
108        // write the copyright details
109        if(attr.containsKey(GpxData.META_COPYRIGHT_LICENSE)
110                || attr.containsKey(GpxData.META_COPYRIGHT_YEAR)) {
111            openAtt("copyright", "author=\""+ attr.get(GpxData.META_COPYRIGHT_AUTHOR) +"\"");
112            if(attr.containsKey(GpxData.META_COPYRIGHT_YEAR)) {
113                simpleTag("year", (String) attr.get(GpxData.META_COPYRIGHT_YEAR));
114            }
115            if(attr.containsKey(GpxData.META_COPYRIGHT_LICENSE)) {
116                simpleTag("license", encode((String) attr.get(GpxData.META_COPYRIGHT_LICENSE)));
117            }
118            closeln("copyright");
119        }
120
121        // write links
122        if(attr.containsKey(GpxData.META_LINKS)) {
123            for (GpxLink link : (Collection<GpxLink>) attr.get(GpxData.META_LINKS)) {
124                gpxLink(link);
125            }
126        }
127
128        // write keywords
129        if (attr.containsKey(GpxData.META_KEYWORDS)) {
130            simpleTag("keywords", (String)attr.get(GpxData.META_KEYWORDS));
131        }
132
133        Bounds bounds = data.recalculateBounds();
134        if(bounds != null)
135        {
136            String b = "minlat=\"" + bounds.getMin().lat() + "\" minlon=\"" + bounds.getMin().lon() +
137            "\" maxlat=\"" + bounds.getMax().lat() + "\" maxlon=\"" + bounds.getMax().lon() + "\"" ;
138            inline("bounds", b);
139        }
140
141        closeln("metadata");
142    }
143
144    private void writeWayPoints() {
145        for (WayPoint pnt : data.waypoints) {
146            wayPoint(pnt, WAY_POINT);
147        }
148    }
149
150    private void writeRoutes() {
151        for (GpxRoute rte : data.routes) {
152            openln("rte");
153            writeAttr(rte.attr);
154            for (WayPoint pnt : rte.routePoints) {
155                wayPoint(pnt, ROUTE_POINT);
156            }
157            closeln("rte");
158        }
159    }
160
161    private void writeTracks() {
162        for (GpxTrack trk : data.tracks) {
163            open("trk");
164            writeAttr(trk.getAttributes());
165            for (GpxTrackSegment seg : trk.getSegments()) {
166                openln("trkseg");
167                for (WayPoint pnt : seg.getWayPoints()) {
168                    wayPoint(pnt, TRACK_POINT);
169                }
170                closeln("trkseg");
171            }
172            closeln("trk");
173        }
174    }
175
176    private void openln(String tag) {
177        open(tag);
178        out.println();
179    }
180
181    private void open(String tag) {
182        out.print(indent + "<" + tag + ">");
183        indent += "  ";
184    }
185
186    private void openAtt(String tag, String attributes) {
187        out.println(indent + "<" + tag + " " + attributes + ">");
188        indent += "  ";
189    }
190
191    private void inline(String tag, String attributes) {
192        out.println(indent + "<" + tag + " " + attributes + " />");
193    }
194
195    private void close(String tag) {
196        indent = indent.substring(2);
197        out.print(indent + "</" + tag + ">");
198    }
199
200    private void closeln(String tag) {
201        close(tag);
202        out.println();
203    }
204
205    /**
206     * if content not null, open tag, write encoded content, and close tag
207     * else do nothing.
208     */
209    private void simpleTag(String tag, String content) {
210        if (content != null && content.length() > 0) {
211            open(tag);
212            out.print(encode(content));
213            out.println("</" + tag + ">");
214            indent = indent.substring(2);
215        }
216    }
217
218    /**
219     * output link
220     */
221    private void gpxLink(GpxLink link) {
222        if (link != null) {
223            openAtt("link", "href=\"" + link.uri + "\"");
224            simpleTag("text", link.text);
225            simpleTag("type", link.type);
226            closeln("link");
227        }
228    }
229
230    /**
231     * output a point
232     */
233    private void wayPoint(WayPoint pnt, int mode) {
234        String type;
235        switch(mode) {
236        case WAY_POINT:
237            type = "wpt";
238            break;
239        case ROUTE_POINT:
240            type = "rtept";
241            break;
242        case TRACK_POINT:
243            type = "trkpt";
244            break;
245        default:
246            throw new RuntimeException(tr("Unknown mode {0}.", mode));
247        }
248        if (pnt != null) {
249            LatLon c = pnt.getCoor();
250            openAtt(type, "lat=\"" + c.lat() + "\" lon=\"" + c.lon() + "\"");
251            writeAttr(pnt.attr);
252            closeln(type);
253        }
254    }
255}
Note: See TracBrowser for help on using the repository browser.