Merge pull request #1425 from twpayne/vector-api-kml-gx-track

[vector-api] KML gx:MultiTrack support
This commit is contained in:
Tom Payne
2013-12-20 08:27:01 -08:00
4 changed files with 215 additions and 4 deletions

View File

@@ -3,7 +3,6 @@
// FIXME handle highlighted keys in StyleMaps - use styleFunctions
// FIXME extractAttributes
// FIXME extractStyles
// FIXME gx:Track
// FIXME http://earth.google.com/kml/1.0 namespace?
// FIXME why does node.getAttribute return an unknown type?
// FIXME text
@@ -49,6 +48,13 @@ ol.KML_RESPECT_VISIBILITY = false;
ol.format.KMLVec2_;
/**
* @typedef {{flatCoordinates: Array.<number>,
* whens: Array.<number>}}
*/
ol.format.KMLGxTrackObject_;
/**
* @constructor
@@ -108,6 +114,15 @@ goog.inherits(ol.format.KML, ol.format.XML);
ol.format.KML.EXTENSIONS_ = ['.kml'];
/**
* @const {Array.<string>}
* @private
*/
ol.format.KML.GX_NAMESPACE_URIS_ = [
'http://www.google.com/kml/ext/2.2'
];
/**
* @const {Array.<string>}
* @private
@@ -553,6 +568,91 @@ ol.format.KML.readFlatLinearRing_ = function(node, objectStack) {
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
ol.format.KML.gxCoordParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
goog.asserts.assert(goog.array.indexOf(
ol.format.KML.GX_NAMESPACE_URIS_, node.namespaceURI) != -1);
goog.asserts.assert(node.localName == 'coord');
var gxTrackObject = /** @type {ol.format.KMLGxTrackObject_} */
(objectStack[objectStack.length - 1]);
goog.asserts.assert(goog.isObject(gxTrackObject));
var flatCoordinates = gxTrackObject.flatCoordinates;
var s = ol.xml.getAllTextContent(node, false);
var re =
/^\s*([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s+([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s+([+\-]?\d+(?:\.\d*)?(?:e[+\-]?\d*)?)\s*$/i;
var m = re.exec(s);
if (m) {
var x = parseFloat(m[1]);
var y = parseFloat(m[2]);
var z = parseFloat(m[3]);
flatCoordinates.push(x, y, z, 0);
} else {
flatCoordinates.push(0, 0, 0, 0);
}
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {ol.geom.MultiLineString|undefined} MultiLineString.
*/
ol.format.KML.readGxMultiTrack_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
goog.asserts.assert(goog.array.indexOf(
ol.format.KML.GX_NAMESPACE_URIS_, node.namespaceURI) != -1);
goog.asserts.assert(node.localName == 'MultiTrack');
var lineStrings = ol.xml.pushAndParse(
/** @type {Array.<ol.geom.LineString>} */ ([]),
ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_, node, objectStack);
if (!goog.isDef(lineStrings)) {
return undefined;
}
var multiLineString = new ol.geom.MultiLineString(null);
multiLineString.setLineStrings(lineStrings);
return multiLineString;
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
* @return {ol.geom.LineString|undefined} LineString.
*/
ol.format.KML.readGxTrack_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
goog.asserts.assert(goog.array.indexOf(
ol.format.KML.GX_NAMESPACE_URIS_, node.namespaceURI) != -1);
goog.asserts.assert(node.localName == 'Track');
var gxTrackObject = ol.xml.pushAndParse(
/** @type {ol.format.KMLGxTrackObject_} */ ({
flatCoordinates: [],
whens: []
}), ol.format.KML.GX_TRACK_PARSERS_, node, objectStack);
if (!goog.isDef(gxTrackObject)) {
return undefined;
}
var flatCoordinates = gxTrackObject.flatCoordinates;
var whens = gxTrackObject.whens;
goog.asserts.assert(flatCoordinates.length / 4 == whens.length);
var i, ii;
for (i = 0, ii = Math.min(flatCoordinates.length, whens.length); i < ii;
++i) {
flatCoordinates[4 * i + 3] = whens[i];
}
var lineString = new ol.geom.LineString(null);
lineString.setFlatCoordinates(ol.geom.GeometryLayout.XYZM, flatCoordinates);
return lineString;
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
@@ -951,6 +1051,45 @@ ol.format.KML.outerBoundaryIsParser_ = function(node, objectStack) {
};
/**
* @param {Node} node Node.
* @param {Array.<*>} objectStack Object stack.
* @private
*/
ol.format.KML.whenParser_ = function(node, objectStack) {
goog.asserts.assert(node.nodeType == goog.dom.NodeType.ELEMENT);
goog.asserts.assert(node.localName == 'when');
var gxTrackObject = /** @type {ol.format.KMLGxTrackObject_} */
(objectStack[objectStack.length - 1]);
goog.asserts.assert(goog.isObject(gxTrackObject));
var whens = gxTrackObject.whens;
var s = ol.xml.getAllTextContent(node, false);
var re =
/^\s*(\d{4})-(\d{2})-(\d{2})T(\d{2}):(\d{2}):(\d{2})(Z|(?:([+\-])(\d{2})(?::(\d{2}))?))\s*$/;
var m = re.exec(s);
if (m) {
var year = parseInt(m[1], 10);
var month = parseInt(m[2], 10) - 1;
var day = parseInt(m[3], 10);
var hour = parseInt(m[4], 10);
var minute = parseInt(m[5], 10);
var second = parseInt(m[6], 10);
var date = new Date(year, month, day, hour, minute, second, 0);
var t = date.getTime() / 1000;
if (m[7] != 'Z') {
var sign = m[8] == '-' ? -1 : 1;
t += sign * 60 * parseInt(m[9], 10);
if (goog.isDef(m[10])) {
t += sign * 60 * 60 * parseInt(m[10], 10);
}
}
whens.push(t);
} else {
whens.push(0);
}
};
/**
* @const {Object.<string, Object.<string, ol.xml.Parser>>}
* @private
@@ -993,6 +1132,19 @@ ol.format.KML.FLAT_LINEAR_RINGS_PARSERS_ = ol.xml.makeParsersNS(
});
/**
* @const {Object.<string, Object.<string, ol.xml.Parser>>}
* @private
*/
ol.format.KML.GX_TRACK_PARSERS_ = ol.xml.makeParsersNS(
ol.format.KML.NAMESPACE_URIS_, {
'when': ol.format.KML.whenParser_
}, ol.xml.makeParsersNS(
ol.format.KML.GX_NAMESPACE_URIS_, {
'coord': ol.format.KML.gxCoordParser_
}));
/**
* @const {Object.<string, Object.<string, ol.xml.Parser>>}
* @private
@@ -1060,6 +1212,16 @@ ol.format.KML.MULTI_GEOMETRY_PARSERS_ = ol.xml.makeParsersNS(
});
/**
* @const {Object.<string, Object.<string, ol.xml.Parser>>}
* @private
*/
ol.format.KML.GX_MULTITRACK_GEOMETRY_PARSERS_ = ol.xml.makeParsersNS(
ol.format.KML.GX_NAMESPACE_URIS_, {
'Track': ol.xml.makeArrayPusher(ol.format.KML.readGxTrack_)
});
/**
* @const {Object.<string, Object.<string, ol.xml.Parser>>}
* @private
@@ -1106,7 +1268,12 @@ ol.format.KML.PLACEMARK_PARSERS_ = ol.xml.makeParsersNS(
'phoneNumber': ol.xml.makeObjectPropertySetter(ol.format.KML.readString_),
'styleUrl': ol.xml.makeObjectPropertySetter(ol.format.KML.readURI_),
'visibility': ol.xml.makeObjectPropertySetter(ol.format.KML.readBoolean_)
});
}, ol.xml.makeParsersNS(
ol.format.KML.GX_NAMESPACE_URIS_, {
'MultiTrack': ol.xml.makeObjectPropertySetter(
ol.format.KML.readGxMultiTrack_, 'geometry')
}
));
/**

View File

@@ -1,5 +1,7 @@
goog.provide('ol.geom.MultiLineString');
goog.require('goog.array');
goog.require('goog.asserts');
goog.require('ol.extent');
goog.require('ol.geom.LineString');
goog.require('ol.geom.SimpleGeometry');
@@ -163,3 +165,26 @@ ol.geom.MultiLineString.prototype.setFlatCoordinates =
this.ends_ = ends;
this.dispatchChangeEvent();
};
/**
* @param {Array.<ol.geom.LineString>} lineStrings LineStrings.
*/
ol.geom.MultiLineString.prototype.setLineStrings = function(lineStrings) {
var layout = ol.geom.GeometryLayout.XY;
var flatCoordinates = [];
var ends = [];
var i, ii;
for (i = 0, ii = lineStrings.length; i < ii; ++i) {
var lineString = lineStrings[i];
if (i === 0) {
layout = lineString.getLayout();
} else {
// FIXME better handle the case of non-matching layouts
goog.asserts.assert(lineString.getLayout() == layout);
}
goog.array.extend(flatCoordinates, lineString.getFlatCoordinates());
ends.push(flatCoordinates.length);
}
this.setFlatCoordinates(layout, flatCoordinates, ends);
};

View File

@@ -149,11 +149,13 @@ ol.xml.makeObjectPropertySetter = function(valueReader, opt_property, opt_obj) {
/**
* @param {Array.<string>} namespaceURIs Namespace URIs.
* @param {Object.<string, ol.xml.Parser>} parsers Parsers.
* @param {Object.<string, Object.<string, ol.xml.Parser>>=} opt_parsersNS
* ParsersNS.
* @return {Object.<string, Object.<string, ol.xml.Parser>>} Parsers NS.
*/
ol.xml.makeParsersNS = function(namespaceURIs, parsers) {
ol.xml.makeParsersNS = function(namespaceURIs, parsers, opt_parsersNS) {
/** @type {Object.<string, Object.<string, ol.xml.Parser>>} */
var parsersNS = {};
var parsersNS = goog.isDef(opt_parsersNS) ? opt_parsersNS : {};
var i, ii;
for (i = 0, ii = namespaceURIs.length; i < ii; ++i) {
parsersNS[namespaceURIs[i]] = parsers;

View File

@@ -168,8 +168,25 @@ describe('ol.geom.MultiLineString', function() {
});
describe('#setLineStrings', function() {
it('sets the line strings', function() {
var multiLineString = new ol.geom.MultiLineString(null);
var lineString1 = new ol.geom.LineString([[1, 2], [3, 4]]);
var lineString2 = new ol.geom.LineString([[5, 6], [7, 8]]);
multiLineString.setLineStrings([lineString1, lineString2]);
expect(multiLineString.getFlatCoordinates()).to.eql(
[1, 2, 3, 4, 5, 6, 7, 8]);
expect(multiLineString.getEnds()).to.eql([4, 8]);
var coordinates = multiLineString.getCoordinates();
expect(coordinates[0]).to.eql(lineString1.getCoordinates());
expect(coordinates[1]).to.eql(lineString2.getCoordinates());
});
});
});
goog.require('ol.extent');
goog.require('ol.geom.LineString');
goog.require('ol.geom.MultiLineString');