Adding support for write in the GPX format, r=marcjansen, (Closes #3495)

git-svn-id: http://svn.openlayers.org/trunk/openlayers@12370 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
pgiraud
2011-09-15 12:27:56 +00:00
parent 2a65d77108
commit f50d1c85d8
3 changed files with 265 additions and 2 deletions

View File

@@ -86,7 +86,8 @@
gml2: new OpenLayers.Format.GML.v2(gmlOptionsIn), gml2: new OpenLayers.Format.GML.v2(gmlOptionsIn),
gml3: new OpenLayers.Format.GML.v3(gmlOptionsIn), gml3: new OpenLayers.Format.GML.v3(gmlOptionsIn),
kml: new OpenLayers.Format.KML(kmlOptionsIn), 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': { 'out': {
wkt: new OpenLayers.Format.WKT(out_options), wkt: new OpenLayers.Format.WKT(out_options),
@@ -95,7 +96,8 @@
gml2: new OpenLayers.Format.GML.v2(gmlOptionsOut), gml2: new OpenLayers.Format.GML.v2(gmlOptionsOut),
gml3: new OpenLayers.Format.GML.v3(gmlOptionsOut), gml3: new OpenLayers.Format.GML.v3(gmlOptionsOut),
kml: new OpenLayers.Format.KML(out_options), 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 @@
<option value="gml2">GML (v2)</option> <option value="gml2">GML (v2)</option>
<option value="gml3">GML (v3)</option> <option value="gml3">GML (v3)</option>
<option value="wkt">Well-Known Text (WKT)</option> <option value="wkt">Well-Known Text (WKT)</option>
<option value="gpx">GPX</option>
</select> </select>
&nbsp; &nbsp;
<label for="prettyPrint">Pretty print</label> <label for="prettyPrint">Pretty print</label>

View File

@@ -20,6 +20,16 @@
* - <OpenLayers.Format.XML> * - <OpenLayers.Format.XML>
*/ */
OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, { 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 * APIProperty: extractWaypoints
* {Boolean} Extract waypoints from GPX. (default: true) * {Boolean} Extract waypoints from GPX. (default: true)
@@ -45,6 +55,13 @@ OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
* be extracted. * be extracted.
*/ */
extractAttributes: true, 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 * Constructor: OpenLayers.Format.GPX
@@ -179,6 +196,170 @@ OpenLayers.Format.GPX = OpenLayers.Class(OpenLayers.Format.XML, {
} }
return attributes; return attributes;
}, },
/**
* APIMethod: write
* Accepts Feature Collection, and returns a string.
*
* Parameters:
* features - {Array(<OpenLayers.Feature.Vector>)} 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<len; i++) {
gpx.appendChild(this.buildFeatureNode(features[i]));
}
if (metadata && typeof metadata == 'object') {
gpx.appendChild(this.buildMetadataNode(metadata));
}
return OpenLayers.Format.XML.prototype.write.apply(this, [gpx]);
},
/**
* Method: buildMetadataNode
* Creates a "metadata" node.
*
* Returns:
* {DOMElement}
*/
buildMetadataNode: function(metadata) {
var types = ['name', 'desc', 'author'],
node = this.createElementNS(this.gpxns, 'metadata');
for (var i=0; i < types.length; i++) {
var type = types[i];
if (metadata[type]) {
var n = this.createElementNS(this.gpxns, type);
n.appendChild(this.createTextNode(metadata[type]));
node.appendChild(n);
}
}
return node;
},
/**
* Method: buildFeatureNode
* Accepts an <OpenLayers.Feature.Vector>, and builds a node for it.
*
* Parameters:
* feature - {<OpenLayers.Feature.Vector>}
*
* 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" CLASS_NAME: "OpenLayers.Format.GPX"
}); });

View File

@@ -34,6 +34,85 @@
t.eq(features[2].attributes['name'], "Mark", "Text attribute node read correctly."); t.eq(features[2].attributes['name'], "Mark", "Text attribute node read correctly.");
t.eq(features[2].attributes['sym'], "Flag", "CDATA 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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><wpt lon="-111.04" lat="45.68"><name>foo</name><desc>bar</desc></wpt><wpt lon="-112.04" lat="45.68"><name>foo</name><desc>bar</desc></wpt></gpx>', '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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><trk><name>foo</name><desc>bar</desc><trkseg><trkpt lon="-111.04" lat="45.68"/><trkpt lon="-112.04" lat="45.68"/></trkseg></trk></gpx>', '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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><trk><name>foo</name><desc>bar</desc><trkseg><trkpt lon="-111.04" lat="45.68"/><trkpt lon="-112.04" lat="45.68"/></trkseg></trk><trk><name>dude</name><desc>truite</desc><trkseg><trkpt lon="1" lat="2"/><trkpt lon="3" lat="4"/></trkseg></trk></gpx>', '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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><trk><name>foo</name><desc>bar</desc><trkseg><trkpt lon="-111.04" lat="45.68"/><trkpt lon="-112.04" lat="45.68"/></trkseg><trkseg><trkpt lon="1" lat="2"/><trkpt lon="3" lat="4"/></trkseg></trk></gpx>', '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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><trk><name>foo</name><desc>bar</desc><trkseg><trkpt lon="-111.04" lat="45.68"/><trkpt lon="-112.04" lat="45.68"/><trkpt lon="-111.04" lat="45.68"/></trkseg></trk></gpx>', '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, '<?xml version="1.0" encoding="ISO-8859-1"?><gpx xmlns="http://www.topografix.com/GPX/1/1"><metadata><name>foo</name><desc>bar</desc></metadata></gpx>', 'GPX serializes metadata correctly');
}
</script> </script>
</head> </head>
<body> <body>