Adding gx:Track parsing to the KML format. If extractTracks is true, the parser will extract points from gx:Track elements as features, acquiring attributes from the Placemark plus when, trackId, altitude, heading, tilt, and roll (assuming angles are present). r=ahocevar (closes #2771)
git-svn-id: http://svn.openlayers.org/trunk/openlayers@10631 dc9f47b5-9b13-0410-9fdd-eb0c1a62fdaf
This commit is contained in:
@@ -24,6 +24,15 @@
|
||||
*/
|
||||
OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
|
||||
|
||||
/**
|
||||
* Property: namespaces
|
||||
* {Object} Mapping of namespace aliases to namespace URIs.
|
||||
*/
|
||||
namespaces: {
|
||||
kml: "http://www.opengis.net/kml/2.2",
|
||||
gx: "http://www.google.com/kml/ext/2.2"
|
||||
},
|
||||
|
||||
/**
|
||||
* APIProperty: kmlns
|
||||
* {String} KML Namespace to use. Defaults to 2.0 namespace.
|
||||
@@ -65,6 +74,26 @@ OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
|
||||
*/
|
||||
extractStyles: false,
|
||||
|
||||
/**
|
||||
* APIProperty: extractTracks
|
||||
* {Boolean} Extract gx:Track elements from Placemark elements. Default
|
||||
* is false. If true, features will be generated for all points in
|
||||
* all gx:Track elements. Features will have a when (Date) attribute
|
||||
* based on when elements in the track. If tracks include angle
|
||||
* elements, features will have heading, tilt, and roll attributes.
|
||||
* If track point coordinates have three values, features will have
|
||||
* an altitude attribute with the third coordinate value.
|
||||
*/
|
||||
extractTracks: false,
|
||||
|
||||
/**
|
||||
* APIProperty: trackAttributes
|
||||
* {Array} If <extractTracks> is true, points within gx:Track elements will
|
||||
* be parsed as features with when, heading, tilt, and roll attributes.
|
||||
* Any additional attribute names can be provided in <trackAttributes>.
|
||||
*/
|
||||
trackAttributes: null,
|
||||
|
||||
/**
|
||||
* Property: internalns
|
||||
* {String} KML Namespace to use -- defaults to the namespace of the
|
||||
@@ -565,7 +594,7 @@ OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
|
||||
*
|
||||
*/
|
||||
parseFeatures: function(nodes, options) {
|
||||
var features = new Array(nodes.length);
|
||||
var features = [];
|
||||
for(var i=0, len=nodes.length; i<len; i++) {
|
||||
var featureNode = nodes[i];
|
||||
var feature = this.parseFeature.apply(this,[featureNode]) ;
|
||||
@@ -593,8 +622,26 @@ OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
|
||||
}
|
||||
}
|
||||
|
||||
// add feature to list of features
|
||||
features[i] = feature;
|
||||
// check if gx:Track elements should be parsed
|
||||
if (this.extractTracks) {
|
||||
var tracks = this.getElementsByTagNameNS(
|
||||
featureNode, this.namespaces.gx, "Track"
|
||||
);
|
||||
if (tracks && tracks.length > 0) {
|
||||
var track = tracks[0];
|
||||
var container = {
|
||||
features: [],
|
||||
feature: feature
|
||||
};
|
||||
this.readNode(track, container);
|
||||
if (container.features.length > 0) {
|
||||
features.push.apply(features, container.features);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
// add feature to list of features
|
||||
features.push(feature);
|
||||
}
|
||||
} else {
|
||||
throw "Bad Placemark: " + i;
|
||||
}
|
||||
@@ -603,7 +650,100 @@ OpenLayers.Format.KML = OpenLayers.Class(OpenLayers.Format.XML, {
|
||||
// add new features to existing feature list
|
||||
this.features = this.features.concat(features);
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* Property: readers
|
||||
* Contains public functions, grouped by namespace prefix, that will
|
||||
* be applied when a namespaced node is found matching the function
|
||||
* name. The function will be applied in the scope of this parser
|
||||
* with two arguments: the node being read and a context object passed
|
||||
* from the parent.
|
||||
*/
|
||||
readers: {
|
||||
"kml": {
|
||||
"when": function(node, container) {
|
||||
container.whens.push(OpenLayers.Date.parse(
|
||||
this.getChildValue(node)
|
||||
));
|
||||
},
|
||||
"_trackPointAttribute": function(node, container) {
|
||||
var name = node.nodeName.split(":").pop();
|
||||
container.attributes[name].push(this.getChildValue(node));
|
||||
}
|
||||
},
|
||||
"gx": {
|
||||
"Track": function(node, container) {
|
||||
var obj = {
|
||||
whens: [],
|
||||
points: [],
|
||||
angles: []
|
||||
};
|
||||
if (this.trackAttributes) {
|
||||
var name;
|
||||
obj.attributes = {};
|
||||
for (var i=0, ii=this.trackAttributes.length; i<ii; ++i) {
|
||||
name = this.trackAttributes[i];
|
||||
obj.attributes[name] = [];
|
||||
if (!(name in this.readers.kml)) {
|
||||
this.readers.kml[name] = this.readers.kml._trackPointAttribute;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.readChildNodes(node, obj);
|
||||
if (obj.whens.length !== obj.points.length) {
|
||||
throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:coord (" + obj.points.length + ") elements.");
|
||||
}
|
||||
var hasAngles = obj.angles.length > 0;
|
||||
if (hasAngles && obj.whens.length !== obj.angles.length) {
|
||||
throw new Error("gx:Track with unequal number of when (" + obj.whens.length + ") and gx:angles (" + obj.angles.length + ") elements.");
|
||||
}
|
||||
var feature, point, angles;
|
||||
for (var i=0, ii=obj.whens.length; i<ii; ++i) {
|
||||
feature = container.feature.clone();
|
||||
feature.fid = container.feature.fid || container.feature.id;
|
||||
point = obj.points[i];
|
||||
feature.geometry = point;
|
||||
if ("z" in point) {
|
||||
feature.attributes.altitude = point.z;
|
||||
}
|
||||
if (this.internalProjection && this.externalProjection) {
|
||||
feature.geometry.transform(
|
||||
this.externalProjection, this.internalProjection
|
||||
);
|
||||
}
|
||||
if (this.trackAttributes) {
|
||||
for (var j=0, jj=this.trackAttributes.length; j<jj; ++j) {
|
||||
feature.attributes[name] = obj.attributes[this.trackAttributes[j]][i];
|
||||
}
|
||||
}
|
||||
feature.attributes.when = obj.whens[i];
|
||||
feature.attributes.trackId = container.feature.id;
|
||||
if (hasAngles) {
|
||||
angles = obj.angles[i];
|
||||
feature.attributes.heading = parseFloat(angles[0]);
|
||||
feature.attributes.tilt = parseFloat(angles[1]);
|
||||
feature.attributes.roll = parseFloat(angles[2]);
|
||||
}
|
||||
container.features.push(feature);
|
||||
}
|
||||
},
|
||||
"coord": function(node, container) {
|
||||
var str = this.getChildValue(node);
|
||||
var coords = str.replace(this.regExes.trimSpace, "").split(/\s+/);
|
||||
var point = new OpenLayers.Geometry.Point(coords[0], coords[1]);
|
||||
if (coords.length > 2) {
|
||||
point.z = parseFloat(coords[2]);
|
||||
}
|
||||
container.points.push(point);
|
||||
},
|
||||
"angles": function(node, container) {
|
||||
var str = this.getChildValue(node);
|
||||
var parts = str.replace(this.regExes.trimSpace, "").split(/\s+/);
|
||||
container.angles.push(parts);
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
/**
|
||||
* Method: parseFeature
|
||||
* This function is the core of the KML parsing code in OpenLayers.
|
||||
|
||||
Reference in New Issue
Block a user