diff --git a/examples/vector-formats.html b/examples/vector-formats.html
index 7848cf3d9e..97b51c7d2f 100644
--- a/examples/vector-formats.html
+++ b/examples/vector-formats.html
@@ -86,7 +86,8 @@
gml2: new OpenLayers.Format.GML.v2(gmlOptionsIn),
gml3: new OpenLayers.Format.GML.v3(gmlOptionsIn),
kml: new OpenLayers.Format.KML(kmlOptionsIn),
- atom: new OpenLayers.Format.Atom(in_options)
+ atom: new OpenLayers.Format.Atom(in_options),
+ gpx: new OpenLayers.Format.GPX(in_options)
},
'out': {
wkt: new OpenLayers.Format.WKT(out_options),
@@ -95,7 +96,8 @@
gml2: new OpenLayers.Format.GML.v2(gmlOptionsOut),
gml3: new OpenLayers.Format.GML.v3(gmlOptionsOut),
kml: new OpenLayers.Format.KML(out_options),
- atom: new OpenLayers.Format.Atom(out_options)
+ atom: new OpenLayers.Format.Atom(out_options),
+ gpx: new OpenLayers.Format.GPX(out_options)
}
};
}
@@ -199,6 +201,7 @@
Vector Formats Example
+
diff --git a/lib/OpenLayers/Format/GPX.js b/lib/OpenLayers/Format/GPX.js
index 63170feea3..2344de9e53 100644
--- a/lib/OpenLayers/Format/GPX.js
+++ b/lib/OpenLayers/Format/GPX.js
@@ -20,6 +20,16 @@
* -
*/
OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
+
+
+ /**
+ * APIProperty: defaultDesc
+ * {String} Default description for the waypoints/tracks in the case
+ * where the feature has no "description" attribute.
+ * Default is "No description available".
+ */
+ defaultDesc: "No description available",
+
/**
* APIProperty: extractWaypoints
* {Boolean} Extract waypoints from GPX. (default: true)
@@ -45,6 +55,13 @@ OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
* be extracted.
*/
extractAttributes: true,
+
+ /**
+ * APIProperty: gpxns
+ * {String} GPX namespace to use. Defaults to
+ * "http://www.topografix.com/GPX/1/1"
+ */
+ gpxns: "http://www.topografix.com/GPX/1/1",
/**
* Constructor: OpenLayers.Format.GPX
@@ -179,6 +196,170 @@ OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
}
return attributes;
},
+
+ /**
+ * APIMethod: write
+ * Accepts Feature Collection, and returns a string.
+ *
+ * Parameters:
+ * features - {Array()} List of features to serialize into a string.
+ * metadata - {Object} A key/value pairs object to build a metadata node to
+ * add to the gpx. Supported keys are 'name', 'desc', 'author'.
+ */
+ write: function(features, metadata) {
+ var gpx;
+ features = OpenLayers.Util.isArray(features) ?
+ features : [features];
+ gpx = this.createElementNS(this.gpxns, "gpx");
+
+ for(var i=0, len=features.length; i, and builds a node for it.
+ *
+ * Parameters:
+ * feature - {}
+ *
+ * Returns:
+ * {DOMElement} - The created node, either a 'wpt' or a 'trk'.
+ */
+ buildFeatureNode: function(feature) {
+ var geometry = feature.geometry;
+ geometry = geometry.clone();
+ if (this.internalProjection && this.externalProjection) {
+ geometry.transform(this.internalProjection,
+ this.externalProjection);
+ }
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.Point") {
+ var wpt = this.buildWptNode(feature);
+ return wpt;
+ } else {
+ var trkNode = this.createElementNS(this.gpxns, "trk");
+ this.appendAttributesNode(trkNode, feature);
+ var trkSegNodes = this.buildTrkSegNode(geometry);
+ trkSegNodes = OpenLayers.Util.isArray(trkSegNodes) ?
+ trkSegNodes : [trkSegNodes];
+ for (var i = 0, len = trkSegNodes.length; i < len; i++) {
+ trkNode.appendChild(trkSegNodes[i]);
+ }
+ return trkNode;
+ }
+ },
+
+ /**
+ * Method: buildTrkSegNode
+ * Builds trkseg node(s) given a geometry
+ *
+ * Parameters:
+ * trknode
+ * geometry - {OpenLayers.Geometry}
+ */
+ buildTrkSegNode: function(geometry) {
+ var node,
+ i,
+ len,
+ point,
+ nodes;
+ if (geometry.CLASS_NAME == "OpenLayers.Geometry.LineString" ||
+ geometry.CLASS_NAME == "OpenLayers.Geometry.LinearRing") {
+ node = this.createElementNS(this.gpxns, "trkseg");
+ for (i = 0, len=geometry.components.length; i < len; i++) {
+ point = geometry.components[i];
+ node.appendChild(this.buildTrkPtNode(point));
+ }
+ return node;
+ } else {
+ nodes = [];
+ for (i = 0, len = geometry.components.length; i < len; i++) {
+ nodes.push(this.buildTrkSegNode(geometry.components[i]));
+ }
+ return nodes;
+ }
+ },
+ /**
+ * Method: buildTrkPtNode
+ * Builds a trkpt node given a point
+ *
+ * Parameters:
+ * line - {OpenLayers.Geometry.Point}
+ *
+ * Returns:
+ * {DOMElement} A trkpt node
+ */
+ buildTrkPtNode: function(point) {
+ var node = this.createElementNS(this.gpxns, "trkpt");
+ node.setAttribute("lon", point.x);
+ node.setAttribute("lat", point.y);
+ return node;
+ },
+
+ /**
+ * Method: buildWptNode
+ * Builds a wpt node given a point
+ *
+ * Parameters:
+ * feature - {OpenLayers.Feature.Vector}
+ *
+ * Returns:
+ * {DOMElement} A wpt node
+ */
+ buildWptNode: function(feature) {
+ var node = this.createElementNS(this.gpxns, "wpt");
+ node.setAttribute("lon", feature.geometry.x);
+ node.setAttribute("lat", feature.geometry.y);
+ this.appendAttributesNode(node, feature);
+ return node;
+ },
+
+ /**
+ * Method: appendAttributesNode
+ * Adds some attributes node.
+ *
+ * Parameters:
+ * node - {DOMElement} the node to append the attribute nodes to.
+ * feature - {OpenLayers.Feature.Vector}
+ */
+ appendAttributesNode: function(node, feature) {
+ var name = this.createElementNS(this.gpxns, 'name');
+ name.appendChild(this.createTextNode(
+ feature.attributes.name || feature.id));
+ node.appendChild(name);
+ var desc = this.createElementNS(this.gpxns, 'desc');
+ desc.appendChild(this.createTextNode(
+ feature.attributes.description || this.defaultDesc));
+ node.appendChild(desc);
+ // TBD - deal with remaining (non name/description) attributes.
+ },
+
CLASS_NAME: "OpenLayers.Format.GPX"
});
diff --git a/tests/Format/GPX.html b/tests/Format/GPX.html
index 0bf897d8d7..2b88e7a9de 100644
--- a/tests/Format/GPX.html
+++ b/tests/Format/GPX.html
@@ -34,6 +34,85 @@
t.eq(features[2].attributes['name'], "Mark", "Text attribute node read correctly.");
t.eq(features[2].attributes['sym'], "Flag", "CDATA attribute node read correctly.");
}
+ function test_Format_GPX_serialize_points(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+ var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68);
+ var features = [
+ new OpenLayers.Feature.Vector(point, {name: 'foo', description: 'bar'}),
+ new OpenLayers.Feature.Vector(point2, {name: 'foo', description: 'bar'})
+ ];
+ var data = parser.write(features);
+ t.xml_eq(data, 'foobarfoobar', 'GPX serializes points correctly');
+ }
+ function test_Format_GPX_serialize_line(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+ var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68);
+ var line = new OpenLayers.Geometry.LineString([point, point2]);
+ var f = new OpenLayers.Feature.Vector(line, {name: 'foo', description: 'bar'});
+ var data = parser.write(f);
+ t.xml_eq(data, 'foobar', 'GPX serializes line correctly');
+ }
+ function test_Format_GPX_serialize_lines(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+ var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68);
+ var line = new OpenLayers.Geometry.LineString([point, point2]);
+ var point3 = new OpenLayers.Geometry.Point(1, 2);
+ var point4 = new OpenLayers.Geometry.Point(3, 4);
+ var line2 = new OpenLayers.Geometry.LineString([point3, point4]);
+ var f = new OpenLayers.Feature.Vector(line, {name: 'foo', description: 'bar'});
+ var f2 = new OpenLayers.Feature.Vector(line2, {name: 'dude', description: 'truite'});
+ var data = parser.write([f, f2]);
+ t.xml_eq(data, 'foobardudetruite', 'GPX serializes lines correctly');
+ }
+ function test_Format_GPX_serialize_multiline(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+ var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68);
+ var line = new OpenLayers.Geometry.LineString([point, point2]);
+ var point3 = new OpenLayers.Geometry.Point(1, 2);
+ var point4 = new OpenLayers.Geometry.Point(3, 4);
+ var line2 = new OpenLayers.Geometry.LineString([point3, point4]);
+ var multiline = new OpenLayers.Geometry.MultiLineString([line, line2]);
+ var f = new OpenLayers.Feature.Vector(multiline, {name: 'foo', description: 'bar'});
+ var data = parser.write([f]);
+ t.xml_eq(data, 'foobar', 'GPX serializes multiline correctly');
+ }
+ function test_Format_GPX_serialize_polygon(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var point = new OpenLayers.Geometry.Point(-111.04, 45.68);
+ var point2 = new OpenLayers.Geometry.Point(-112.04, 45.68);
+ var linearRing = new OpenLayers.Geometry.LinearRing([point, point2, point.clone()]);
+ var polygon = new OpenLayers.Geometry.Polygon([linearRing]);
+ var f = new OpenLayers.Feature.Vector(polygon, {name: 'foo', description: 'bar'});
+ var data = parser.write([f]);
+ t.xml_eq(data, 'foobar', 'GPX serializes polygon correctly');
+ }
+ function test_Format_GPX_serialize_metadata(t) {
+ t.plan(1);
+
+ var parser = new OpenLayers.Format.GPX();
+
+ var data = parser.write([], {name: 'foo', desc: 'bar'});
+ t.xml_eq(data, 'foobar', 'GPX serializes metadata correctly');
+ }