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

Last change on this file since 3775 was 2907, checked in by jttt, 14 years ago

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
File size: 8.0 KB
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.