Merge pull request #725 from bartvde/gpx
Implement GPX parser (read/write). (r=@fredj)
This commit is contained in:
@@ -340,6 +340,31 @@
|
||||
* geometries. Default is `false´. This only applies to GML version 3.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ol.parser.GPXOptions
|
||||
* @property {string|undefined} creator The creator attribute to be added to
|
||||
* the written GPX files. Defaults to `OpenLayers´.
|
||||
* @property {string|undefined} defaultDesc Default description for the
|
||||
* waypoints/tracks in the case where the feature has no 'description'
|
||||
* attribute. Default is 'No description available'.
|
||||
* @property {boolean|undefined} extractAttributes Should we extract attributes
|
||||
* from the GPX? Default is `true´.
|
||||
* @property {boolean|undefined} extractWaypoints Extract waypoints from GPX.
|
||||
* Default is `true´.
|
||||
* @property {boolean|undefined} extractTracks Extract tracks from GPX.
|
||||
* Default is `true´.
|
||||
* @property {boolean|undefined} extractRoutes Extract routes from GPX.
|
||||
* Default is `true´.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ol.parser.GPXWriteOptions
|
||||
* @property {Array.<ol.Feature>|ol.Feature} features The features to write
|
||||
* out.
|
||||
* @property {Object|undefined} metadata Metadata key/value pair with keys:
|
||||
* name, desc and author.
|
||||
*/
|
||||
|
||||
/**
|
||||
* @typedef {Object} ol.source.BingMapsOptions
|
||||
* @property {string|undefined} culture Culture.
|
||||
|
||||
3
src/ol/parser/gpx.exports
Normal file
3
src/ol/parser/gpx.exports
Normal file
@@ -0,0 +1,3 @@
|
||||
@exportSymbol ol.parser.GPX
|
||||
@exportProperty ol.parser.GPX.prototype.read
|
||||
@exportProperty ol.parser.GPX.prototype.write
|
||||
310
src/ol/parser/gpx.js
Normal file
310
src/ol/parser/gpx.js
Normal file
@@ -0,0 +1,310 @@
|
||||
goog.provide('ol.parser.GPX');
|
||||
|
||||
goog.require('goog.dom.xml');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.Point');
|
||||
goog.require('ol.geom.Polygon');
|
||||
goog.require('ol.parser.DomFeatureParser');
|
||||
goog.require('ol.parser.ObjectFeatureParser');
|
||||
goog.require('ol.parser.ReadFeaturesOptions');
|
||||
goog.require('ol.parser.StringFeatureParser');
|
||||
goog.require('ol.parser.XML');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
* @constructor
|
||||
* @implements {ol.parser.DomFeatureParser}
|
||||
* @implements {ol.parser.StringFeatureParser}
|
||||
* @implements {ol.parser.ObjectFeatureParser}
|
||||
* @param {ol.parser.GPXOptions=} opt_options Optional configuration object.
|
||||
* @extends {ol.parser.XML}
|
||||
*/
|
||||
ol.parser.GPX = function(opt_options) {
|
||||
var options = /** @type {ol.parser.GPXOptions} */
|
||||
(goog.isDef(opt_options) ? opt_options : {});
|
||||
this.extractAttributes = goog.isDef(options.extractAttributes) ?
|
||||
options.extractAttributes : true;
|
||||
this.extractWaypoints = goog.isDef(options.extractWaypoints) ?
|
||||
options.extractWaypoints : true;
|
||||
this.extractTracks = goog.isDef(options.extractTracks) ?
|
||||
options.extractTracks : true;
|
||||
this.extractRoutes = goog.isDef(options.extractRoutes) ?
|
||||
options.extractRoutes : true;
|
||||
this.creator = goog.isDef(options.creator) ?
|
||||
options.creator : 'OpenLayers';
|
||||
this.defaultDesc = goog.isDef(options.defaultDesc) ?
|
||||
options.defaultDesc : 'No description available';
|
||||
this.defaultNamespaceURI = 'http://www.topografix.com/GPX/1/1';
|
||||
this.schemaLocation = 'http://www.topografix.com/GPX/1/1 ' +
|
||||
'http://www.topografix.com/GPX/1/1/gpx.xsd';
|
||||
this.readers = {
|
||||
'http://www.topografix.com/GPX/1/1': {
|
||||
'gpx': function(node, obj) {
|
||||
if (!goog.isDef(obj.features)) {
|
||||
obj.features = [];
|
||||
}
|
||||
this.readChildNodes(node, obj);
|
||||
},
|
||||
'wpt': function(node, obj) {
|
||||
if (this.extractWaypoints) {
|
||||
var properties = {};
|
||||
var coordinates = [parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat'))];
|
||||
this.readChildNodes(node, properties);
|
||||
var feature = new ol.Feature(properties);
|
||||
var sharedVertices;
|
||||
if (this.readFeaturesOptions_) {
|
||||
var callback = this.readFeaturesOptions_.callback;
|
||||
if (callback) {
|
||||
sharedVertices = callback(feature, ol.geom.GeometryType.POINT);
|
||||
}
|
||||
}
|
||||
var geometry = new ol.geom.Point(coordinates, sharedVertices);
|
||||
feature.setGeometry(geometry);
|
||||
obj.features.push(feature);
|
||||
}
|
||||
},
|
||||
'rte': function(node, obj) {
|
||||
if (this.extractRoutes || obj.force) {
|
||||
var type = ol.geom.GeometryType.LINESTRING;
|
||||
var container = {
|
||||
properties: {},
|
||||
geometry: {
|
||||
type: type,
|
||||
coordinates: []
|
||||
}
|
||||
};
|
||||
this.readChildNodes(node, container);
|
||||
var feature = new ol.Feature(container.properties);
|
||||
var sharedVertices;
|
||||
if (this.readFeaturesOptions_) {
|
||||
var callback = this.readFeaturesOptions_.callback;
|
||||
if (callback) {
|
||||
sharedVertices = callback(feature, type);
|
||||
}
|
||||
}
|
||||
var geometry = new ol.geom.LineString(container.geometry.coordinates,
|
||||
sharedVertices);
|
||||
feature.setGeometry(geometry);
|
||||
obj.features.push(feature);
|
||||
}
|
||||
},
|
||||
'rtept': function(node, container) {
|
||||
var coordinate = [parseFloat(node.getAttribute('lon')),
|
||||
parseFloat(node.getAttribute('lat'))];
|
||||
container.geometry.coordinates.push(coordinate);
|
||||
},
|
||||
'trk': function(node, obj) {
|
||||
if (this.extractTracks) {
|
||||
var readers = this.readers[this.defaultNamespaceURI];
|
||||
obj.force = true;
|
||||
readers['rte'].apply(this, arguments);
|
||||
}
|
||||
},
|
||||
'trkseg': function(node, container) {
|
||||
this.readChildNodes(node, container);
|
||||
},
|
||||
'trkpt': function(node, container) {
|
||||
var readers = this.readers[this.defaultNamespaceURI];
|
||||
readers['rtept'].apply(this, arguments);
|
||||
},
|
||||
'*': function(node, obj) {
|
||||
if (this.extractAttributes === true) {
|
||||
var len = node.childNodes.length;
|
||||
if ((len === 1 || len === 2) && (node.firstChild.nodeType === 3 ||
|
||||
node.firstChild.nodeType === 4)) {
|
||||
var readers = this.readers[this.defaultNamespaceURI];
|
||||
readers['_attribute'].apply(this, arguments);
|
||||
}
|
||||
}
|
||||
},
|
||||
'_attribute': function(node, obj) {
|
||||
var local = node.localName || node.nodeName.split(':').pop();
|
||||
var value = this.getChildValue(node);
|
||||
if (obj.properties) {
|
||||
obj.properties[local] = value.replace(this.regExes.trimSpace, '');
|
||||
} else {
|
||||
obj[local] = value.replace(this.regExes.trimSpace, '');
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
// create an alias for GXP 1.0
|
||||
this.readers['http://www.topografix.com/GPX/1/0'] =
|
||||
this.readers[this.defaultNamespaceURI];
|
||||
this.writers = {
|
||||
'http://www.topografix.com/GPX/1/1': {
|
||||
'_feature': function(feature) {
|
||||
var geom = feature.getGeometry();
|
||||
if (geom instanceof ol.geom.Point) {
|
||||
return this.writeNode('wpt', feature);
|
||||
} else if ((geom instanceof ol.geom.LineString) ||
|
||||
(geom instanceof ol.geom.MultiLineString) ||
|
||||
(geom instanceof ol.geom.Polygon)) {
|
||||
return this.writeNode('trk', feature);
|
||||
}
|
||||
},
|
||||
'wpt': function(feature) {
|
||||
var node = this.createElementNS('wpt');
|
||||
var geom = feature.getGeometry();
|
||||
var coordinates = geom.getCoordinates();
|
||||
node.setAttribute('lon', coordinates[0]);
|
||||
node.setAttribute('lat', coordinates[1]);
|
||||
var attributes = feature.getAttributes();
|
||||
var name = attributes['name'] || goog.getUid(feature).toString();
|
||||
this.writeNode('name', name, undefined, node);
|
||||
var desc = attributes['description'] || this.defaultDesc;
|
||||
this.writeNode('desc', desc, undefined, node);
|
||||
return node;
|
||||
},
|
||||
'trk': function(feature) {
|
||||
var attributes = feature.getAttributes();
|
||||
var node = this.createElementNS('trk');
|
||||
var name = attributes['name'] || goog.getUid(feature).toString();
|
||||
this.writeNode('name', name, undefined, node);
|
||||
var desc = attributes['description'] || this.defaultDesc;
|
||||
this.writeNode('desc', desc, undefined, node);
|
||||
var geom = feature.getGeometry();
|
||||
var i, ii;
|
||||
if (geom instanceof ol.geom.LineString) {
|
||||
this.writeNode('trkseg', feature.getGeometry(), undefined, node);
|
||||
} else if (geom instanceof ol.geom.MultiLineString) {
|
||||
for (i = 0, ii = geom.components.length; i < ii; ++i) {
|
||||
this.writeNode('trkseg', geom.components[i], undefined, node);
|
||||
}
|
||||
} else if (geom instanceof ol.geom.Polygon) {
|
||||
for (i = 0, ii = geom.rings.length; i < ii; ++i) {
|
||||
this.writeNode('trkseg', geom.rings[i], undefined, node);
|
||||
}
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'trkseg': function(geometry) {
|
||||
var node = this.createElementNS('trkseg');
|
||||
var coordinates = geometry.getCoordinates();
|
||||
for (var i = 0, ii = coordinates.length; i < ii; ++i) {
|
||||
this.writeNode('trkpt', coordinates[i], undefined, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'trkpt': function(coord) {
|
||||
var node = this.createElementNS('trkpt');
|
||||
node.setAttribute('lon', coord[0]);
|
||||
node.setAttribute('lat', coord[1]);
|
||||
return node;
|
||||
},
|
||||
'metadata': function(metadata) {
|
||||
var node = this.createElementNS('metadata');
|
||||
if (goog.isDef(metadata['name'])) {
|
||||
this.writeNode('name', metadata['name'], undefined, node);
|
||||
}
|
||||
if (goog.isDef(metadata['desc'])) {
|
||||
this.writeNode('desc', metadata['desc'], undefined, node);
|
||||
}
|
||||
if (goog.isDef(metadata['author'])) {
|
||||
this.writeNode('author', metadata['author'], undefined, node);
|
||||
}
|
||||
return node;
|
||||
},
|
||||
'name': function(name) {
|
||||
var node = this.createElementNS('name');
|
||||
node.appendChild(this.createTextNode(name));
|
||||
return node;
|
||||
},
|
||||
'desc': function(desc) {
|
||||
var node = this.createElementNS('desc');
|
||||
node.appendChild(this.createTextNode(desc));
|
||||
return node;
|
||||
},
|
||||
'author': function(author) {
|
||||
var node = this.createElementNS('author');
|
||||
node.appendChild(this.createTextNode(author));
|
||||
return node;
|
||||
}
|
||||
}
|
||||
};
|
||||
goog.base(this);
|
||||
};
|
||||
goog.inherits(ol.parser.GPX, ol.parser.XML);
|
||||
|
||||
|
||||
/**
|
||||
* @param {string|Document|Element|Object} data Data to read.
|
||||
* @return {Object} An object representing the document.
|
||||
*/
|
||||
ol.parser.GPX.prototype.read = function(data) {
|
||||
if (goog.isString(data)) {
|
||||
data = goog.dom.xml.loadXml(data);
|
||||
}
|
||||
if (data && data.nodeType == 9) {
|
||||
data = data.documentElement;
|
||||
}
|
||||
var obj = {};
|
||||
this.readNode(data, obj);
|
||||
return obj;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse a GPX document provided as a string.
|
||||
* @param {string} str GPX document.
|
||||
* @param {ol.parser.ReadFeaturesOptions=} opt_options Reader options.
|
||||
* @return {Array.<ol.Feature>} Array of features.
|
||||
*/
|
||||
ol.parser.GPX.prototype.readFeaturesFromString =
|
||||
function(str, opt_options) {
|
||||
this.readFeaturesOptions_ = opt_options;
|
||||
return this.read(str).features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* Parse a GPX document provided as a DOM structure.
|
||||
* @param {Element|Document} node Document or element node.
|
||||
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
|
||||
* @return {Array.<ol.Feature>} Array of features.
|
||||
*/
|
||||
ol.parser.GPX.prototype.readFeaturesFromNode =
|
||||
function(node, opt_options) {
|
||||
this.readFeaturesOptions_ = opt_options;
|
||||
return this.read(node).features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Object} obj Object representing features.
|
||||
* @param {ol.parser.ReadFeaturesOptions=} opt_options Feature reading options.
|
||||
* @return {Array.<ol.Feature>} Array of features.
|
||||
*/
|
||||
ol.parser.GPX.prototype.readFeaturesFromObject =
|
||||
function(obj, opt_options) {
|
||||
this.readFeaturesOptions_ = opt_options;
|
||||
return this.read(obj).features;
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {ol.parser.GPXWriteOptions} obj Object structure to write out
|
||||
* as GPX.
|
||||
* @return {string} An string representing the GPX document.
|
||||
*/
|
||||
ol.parser.GPX.prototype.write = function(obj) {
|
||||
var features = goog.isArray(obj.features) ? obj.features : [obj.features];
|
||||
var root = this.createElementNS('gpx');
|
||||
root.setAttribute('version', '1.1');
|
||||
root.setAttribute('creator', this.creator);
|
||||
this.setAttributeNS(
|
||||
root, 'http://www.w3.org/2001/XMLSchema-instance',
|
||||
'xsi:schemaLocation', this.schemaLocation);
|
||||
if (goog.isDef(obj.metadata)) {
|
||||
this.writeNode('metadata', obj.metadata, undefined, root);
|
||||
}
|
||||
for (var i = 0, ii = features.length; i < ii; i++) {
|
||||
this.writeNode('_feature', features[i], undefined, root);
|
||||
}
|
||||
return this.serialize(root);
|
||||
};
|
||||
Reference in New Issue
Block a user