Add write support to KML format
This commit is contained in:
@@ -1,6 +1,7 @@
|
||||
// FIXME http://earth.google.com/kml/1.0 namespace?
|
||||
// FIXME why does node.getAttribute return an unknown type?
|
||||
// FIXME text
|
||||
// FIXME serialize arbitrary feature properties
|
||||
|
||||
goog.provide('ol.format.KML');
|
||||
|
||||
@@ -13,12 +14,15 @@ goog.require('goog.object');
|
||||
goog.require('goog.string');
|
||||
goog.require('ol.Feature');
|
||||
goog.require('ol.array');
|
||||
goog.require('ol.color');
|
||||
goog.require('ol.feature');
|
||||
goog.require('ol.format.XMLFeature');
|
||||
goog.require('ol.format.XSD');
|
||||
goog.require('ol.geom.Geometry');
|
||||
goog.require('ol.geom.GeometryCollection');
|
||||
goog.require('ol.geom.GeometryType');
|
||||
goog.require('ol.geom.LineString');
|
||||
goog.require('ol.geom.LinearRing');
|
||||
goog.require('ol.geom.MultiLineString');
|
||||
goog.require('ol.geom.MultiPoint');
|
||||
goog.require('ol.geom.MultiPolygon');
|
||||
@@ -32,6 +36,7 @@ goog.require('ol.style.IconOrigin');
|
||||
goog.require('ol.style.Image');
|
||||
goog.require('ol.style.Stroke');
|
||||
goog.require('ol.style.Style');
|
||||
goog.require('ol.style.Text');
|
||||
goog.require('ol.xml');
|
||||
|
||||
|
||||
@@ -1641,3 +1646,889 @@ ol.format.KML.prototype.readProjectionFromDocument = function(doc) {
|
||||
ol.format.KML.prototype.readProjectionFromNode = function(node) {
|
||||
return ol.proj.get('EPSG:4326');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the boolean to.
|
||||
* @param {boolean} bool Boolean.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeBooleanTextNode_ = function(node, bool) {
|
||||
ol.format.XSD.writeStringTextNode(node, (bool) ? '1' : '0');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the color to.
|
||||
* @param {ol.Color|string} color Color.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeColorTextNode_ = function(node, color) {
|
||||
var rgba = ol.color.asArray(color);
|
||||
var opacity = (rgba.length == 4) ? rgba[3] : 1;
|
||||
var abgr = [opacity * 255, rgba[2], rgba[1], rgba[0]];
|
||||
var i;
|
||||
for (i = 0; i < 4; ++i) {
|
||||
var hex = parseInt(abgr[i], 10).toString(16);
|
||||
abgr[i] = (hex.length == 1) ? '0' + hex : hex;
|
||||
}
|
||||
ol.format.XSD.writeStringTextNode(node, abgr.join(''));
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the coordinates to.
|
||||
* @param {Array.<number>} coordinates Coordinates.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeCoordinatesTextNode_ =
|
||||
function(node, coordinates, objectStack) {
|
||||
var context = objectStack[objectStack.length - 1];
|
||||
goog.asserts.assert(goog.isObject(context));
|
||||
|
||||
var layout = goog.object.get(context, 'layout');
|
||||
var stride = goog.object.get(context, 'stride');
|
||||
|
||||
var dimension;
|
||||
if (layout == ol.geom.GeometryLayout.XY ||
|
||||
layout == ol.geom.GeometryLayout.XYM) {
|
||||
dimension = 2;
|
||||
} else if (layout == ol.geom.GeometryLayout.XYZ ||
|
||||
layout == ol.geom.GeometryLayout.XYZM) {
|
||||
dimension = 3;
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
}
|
||||
|
||||
var d, i;
|
||||
var ii = coordinates.length;
|
||||
var text = '';
|
||||
if (ii > 0) {
|
||||
text += coordinates[0];
|
||||
for (d = 1; d < dimension; ++d) {
|
||||
text += ',' + coordinates[d];
|
||||
}
|
||||
for (i = stride; i < ii; i += stride) {
|
||||
text += ' ' + coordinates[i];
|
||||
for (d = 1; d < dimension; ++d) {
|
||||
text += ',' + coordinates[i + d];
|
||||
}
|
||||
}
|
||||
}
|
||||
ol.format.XSD.writeStringTextNode(node, text);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeDocument_ = function(node, features, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.DOCUMENT_SERIALIZERS_,
|
||||
ol.format.KML.DOCUMENT_NODE_FACTORY_, features, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {Object} icon Icon object.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeIcon_ = function(node, icon, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.KML.ICON_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(icon, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.ICON_SERIALIZERS_, ol.xml.OBJECT_PROPERTY_NODE_FACTORY,
|
||||
values, objectStack, orderedKeys);
|
||||
orderedKeys =
|
||||
ol.format.KML.ICON_SEQUENCE_[ol.format.KML.GX_NAMESPACE_URIS_[0]];
|
||||
values = ol.xml.makeSequence(icon, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.ICON_SERIALIZERS_,
|
||||
ol.format.KML.GX_NODE_FACTORY_, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.style.Icon} style Icon style.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeIconStyle_ = function(node, style, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
var properties = {};
|
||||
var src = style.getSrc();
|
||||
var size = style.getSize();
|
||||
var iconImageSize = style.getImageSize();
|
||||
var iconProperties = {
|
||||
'href': src
|
||||
};
|
||||
|
||||
if (!goog.isNull(size)) {
|
||||
goog.object.set(iconProperties, 'w', size[0]);
|
||||
goog.object.set(iconProperties, 'h', size[1]);
|
||||
var anchor = style.getAnchor(); // top-left
|
||||
var origin = style.getOrigin(); // top-left
|
||||
|
||||
if (!goog.isNull(origin) && !goog.isNull(iconImageSize) &&
|
||||
origin[0] !== 0 && origin[1] !== size[1]) {
|
||||
goog.object.set(iconProperties, 'x', origin[0]);
|
||||
goog.object.set(iconProperties, 'y',
|
||||
iconImageSize[1] - (origin[1] + size[1]));
|
||||
}
|
||||
|
||||
if (!goog.isNull(anchor) &&
|
||||
anchor[0] !== 0 && anchor[1] !== size[1]) {
|
||||
var /** @type {ol.format.KMLVec2_} */ hotSpot = {
|
||||
x: anchor[0],
|
||||
xunits: ol.style.IconAnchorUnits.PIXELS,
|
||||
y: size[1] - anchor[1],
|
||||
yunits: ol.style.IconAnchorUnits.PIXELS
|
||||
};
|
||||
goog.object.set(properties, 'hotSpot', hotSpot);
|
||||
}
|
||||
}
|
||||
|
||||
goog.object.set(properties, 'Icon', iconProperties);
|
||||
|
||||
var scale = style.getScale();
|
||||
if (scale !== 1) {
|
||||
goog.object.set(properties, 'scale', scale);
|
||||
}
|
||||
|
||||
var rotation = style.getRotation();
|
||||
if (rotation !== 0) {
|
||||
goog.object.set(properties, 'heading', rotation); // 0-360
|
||||
}
|
||||
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.KML.ICON_STYLE_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.ICON_STYLE_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.style.Text} style style.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeLabelStyle_ = function(node, style, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
var properties = {};
|
||||
var fill = style.getFill();
|
||||
if (!goog.isNull(fill)) {
|
||||
goog.object.set(properties, 'color', fill.getColor());
|
||||
}
|
||||
var scale = style.getScale();
|
||||
if (goog.isDef(scale) && scale !== 1) {
|
||||
goog.object.set(properties, 'scale', scale);
|
||||
}
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys =
|
||||
ol.format.KML.LABEL_STYLE_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.LABEL_STYLE_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.style.Stroke} style style.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeLineStyle_ = function(node, style, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
var properties = {
|
||||
'color': style.getColor(),
|
||||
'width': style.getWidth()
|
||||
};
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.KML.LINE_STYLE_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.LINE_STYLE_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.geom.Geometry} geometry Geometry.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeMultiGeometry_ =
|
||||
function(node, geometry, objectStack) {
|
||||
goog.asserts.assert(
|
||||
(geometry instanceof ol.geom.MultiPoint) ||
|
||||
(geometry instanceof ol.geom.MultiLineString) ||
|
||||
(geometry instanceof ol.geom.MultiPolygon));
|
||||
/** @type {ol.xml.NodeStackItem} */
|
||||
var context = {node: node};
|
||||
var type = geometry.getType();
|
||||
/** @type {Array.<ol.geom.Geometry>} */
|
||||
var geometries;
|
||||
/** @type {function(*, Array.<*>, string=): (Node|undefined)} */
|
||||
var factory;
|
||||
if (type == ol.geom.GeometryType.MULTI_POINT) {
|
||||
geometries =
|
||||
(/** @type {ol.geom.MultiPoint} */ (geometry)).getPoints();
|
||||
factory = ol.format.KML.POINT_NODE_FACTORY_;
|
||||
} else if (type == ol.geom.GeometryType.MULTI_LINE_STRING) {
|
||||
geometries =
|
||||
(/** @type {ol.geom.MultiLineString} */ (geometry)).getLineStrings();
|
||||
factory = ol.format.KML.LINE_STRING_NODE_FACTORY_;
|
||||
} else if (type == ol.geom.GeometryType.MULTI_POLYGON) {
|
||||
geometries =
|
||||
(/** @type {ol.geom.MultiPolygon} */ (geometry)).getPolygons();
|
||||
factory = ol.format.KML.POLYGON_NODE_FACTORY_;
|
||||
} else {
|
||||
goog.asserts.fail();
|
||||
}
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_, factory,
|
||||
geometries, objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.geom.LinearRing} linearRing Linear ring.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeBoundaryIs_ = function(node, linearRing, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.BOUNDARY_IS_SERIALIZERS_,
|
||||
ol.format.KML.LINEAR_RING_NODE_FACTORY_, [linearRing], objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* FIXME currently we do serialize arbitrary/custom feature properties
|
||||
* (ExtendedData).
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.Feature} feature Feature.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writePlacemark_ = function(node, feature, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
|
||||
// set id
|
||||
if (goog.isDefAndNotNull(feature.getId())) {
|
||||
node.setAttribute('id', feature.getId());
|
||||
}
|
||||
|
||||
// serialize geometry
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
|
||||
ol.format.KML.GEOMETRY_NODE_FACTORY_,
|
||||
[feature.getGeometry()], objectStack);
|
||||
|
||||
// serialize properties (properties unknown to KML are not serialized)
|
||||
var properties = feature.getProperties();
|
||||
var styleFunction = feature.getStyleFunction();
|
||||
if (goog.isDef(styleFunction)) {
|
||||
// FIXME the styles returned by the style function are supposed to be
|
||||
// resolution-independent here
|
||||
var styles = styleFunction.call(feature, 0);
|
||||
if (!goog.isNull(styles) && styles.length > 0) {
|
||||
goog.object.set(properties, 'Style', styles[0]);
|
||||
var textStyle = styles[0].getText();
|
||||
if (!goog.isNull(textStyle)) {
|
||||
goog.object.set(properties, 'name', textStyle.getText());
|
||||
}
|
||||
}
|
||||
}
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.KML.PLACEMARK_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.PLACEMARK_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.geom.SimpleGeometry} geometry Geometry.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writePrimitiveGeometry_ = function(node, geometry, objectStack) {
|
||||
goog.asserts.assert(
|
||||
(geometry instanceof ol.geom.Point) ||
|
||||
(geometry instanceof ol.geom.LineString) ||
|
||||
(geometry instanceof ol.geom.LinearRing));
|
||||
var flatCoordinates = geometry.getFlatCoordinates();
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
goog.object.set(context, 'layout', geometry.getLayout());
|
||||
goog.object.set(context, 'stride', geometry.getStride());
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_,
|
||||
ol.format.KML.COORDINATES_NODE_FACTORY_,
|
||||
[flatCoordinates], objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.geom.Polygon} polygon Polygon.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writePolygon_ = function(node, polygon, objectStack) {
|
||||
goog.asserts.assertInstanceof(polygon, ol.geom.Polygon);
|
||||
var linearRings = polygon.getLinearRings();
|
||||
goog.asserts.assert(linearRings.length > 0);
|
||||
var outerRing = linearRings.shift();
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
// inner rings
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.POLYGON_SERIALIZERS_,
|
||||
ol.format.KML.INNER_BOUNDARY_NODE_FACTORY_,
|
||||
linearRings, objectStack);
|
||||
// outer ring
|
||||
ol.xml.pushSerializeAndPop(context,
|
||||
ol.format.KML.POLYGON_SERIALIZERS_,
|
||||
ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_,
|
||||
[outerRing], objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.style.Fill} style Style.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writePolyStyle_ = function(node, style, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.POLY_STYLE_SERIALIZERS_,
|
||||
ol.format.KML.COLOR_NODE_FACTORY_, [style.getColor()], objectStack);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the scale to.
|
||||
* @param {number|undefined} scale Scale.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeScaleTextNode_ = function(node, scale) {
|
||||
ol.format.XSD.writeDecimalTextNode(node, scale * scale);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node.
|
||||
* @param {ol.style.Style} style Style.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeStyle_ = function(node, style, objectStack) {
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: node};
|
||||
var properties = {};
|
||||
var fillStyle = style.getFill();
|
||||
var strokeStyle = style.getStroke();
|
||||
var imageStyle = style.getImage();
|
||||
var textStyle = style.getText();
|
||||
if (!goog.isNull(imageStyle)) {
|
||||
goog.object.set(properties, 'IconStyle', imageStyle);
|
||||
}
|
||||
if (!goog.isNull(textStyle)) {
|
||||
goog.object.set(properties, 'LabelStyle', textStyle);
|
||||
}
|
||||
if (!goog.isNull(strokeStyle)) {
|
||||
goog.object.set(properties, 'LineStyle', strokeStyle);
|
||||
}
|
||||
if (!goog.isNull(fillStyle)) {
|
||||
goog.object.set(properties, 'PolyStyle', fillStyle);
|
||||
}
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
var orderedKeys = ol.format.KML.STYLE_SEQUENCE_[parentNode.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.STYLE_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, objectStack, orderedKeys);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @param {Node} node Node to append a TextNode with the Vec2 to.
|
||||
* @param {ol.format.KMLVec2_} vec2 Vec2.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.writeVec2_ = function(node, vec2) {
|
||||
node.setAttribute('x', vec2.x);
|
||||
node.setAttribute('y', vec2.y);
|
||||
node.setAttribute('xunits', vec2.xunits);
|
||||
node.setAttribute('yunits', vec2.yunits);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.KML_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'Document', 'Placemark'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.KML_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'Document': ol.xml.makeChildAppender(ol.format.KML.writeDocument_),
|
||||
'Placemark': ol.xml.makeChildAppender(ol.format.KML.writePlacemark_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.DOCUMENT_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'Placemark'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.DOCUMENT_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'Placemark': ol.xml.makeChildAppender(ol.format.KML.writePlacemark_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, string>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.GEOMETRY_TYPE_TO_NODENAME_ = {
|
||||
'Point': 'Point',
|
||||
'LineString': 'LineString',
|
||||
'LinearRing': 'LinearRing',
|
||||
'Polygon': 'Polygon',
|
||||
'MultiPoint': 'MultiGeometry',
|
||||
'MultiLineString': 'MultiGeometry',
|
||||
'MultiPolygon': 'MultiGeometry'
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.ICON_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'href'
|
||||
],
|
||||
ol.xml.makeStructureNS(
|
||||
ol.format.KML.GX_NAMESPACE_URIS_, [
|
||||
'x', 'y', 'w', 'h'
|
||||
]));
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.ICON_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'href': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode)
|
||||
}, ol.xml.makeStructureNS(
|
||||
ol.format.KML.GX_NAMESPACE_URIS_, {
|
||||
'x': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'y': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'w': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'h': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode)
|
||||
}));
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.ICON_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'Icon', 'heading', 'hotSpot', 'scale'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.ICON_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'Icon': ol.xml.makeChildAppender(ol.format.KML.writeIcon_),
|
||||
'heading': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode),
|
||||
'hotSpot': ol.xml.makeChildAppender(ol.format.KML.writeVec2_),
|
||||
'scale': ol.xml.makeChildAppender(ol.format.KML.writeScaleTextNode_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LABEL_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'color', 'scale'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LABEL_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_),
|
||||
'scale': ol.xml.makeChildAppender(ol.format.KML.writeScaleTextNode_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LINE_STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'color', 'width'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LINE_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_),
|
||||
'width': ol.xml.makeChildAppender(ol.format.XSD.writeDecimalTextNode)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.BOUNDARY_IS_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'LinearRing': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.MULTI_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'LineString': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_),
|
||||
'Point': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_),
|
||||
'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.PLACEMARK_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'Style', 'address', 'description', 'name', 'open',
|
||||
'phoneNumber', 'styleUrl', 'visibility'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.PLACEMARK_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'MultiGeometry': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writeMultiGeometry_),
|
||||
'LineString': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_),
|
||||
'LinearRing': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_),
|
||||
'Point': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writePrimitiveGeometry_),
|
||||
'Polygon': ol.xml.makeChildAppender(ol.format.KML.writePolygon_),
|
||||
'Style': ol.xml.makeChildAppender(ol.format.KML.writeStyle_),
|
||||
'address': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'description': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeStringTextNode),
|
||||
'name': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'open': ol.xml.makeChildAppender(ol.format.KML.writeBooleanTextNode_),
|
||||
'phoneNumber': ol.xml.makeChildAppender(
|
||||
ol.format.XSD.writeStringTextNode),
|
||||
'styleUrl': ol.xml.makeChildAppender(ol.format.XSD.writeStringTextNode),
|
||||
'visibility': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writeBooleanTextNode_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.PRIMITIVE_GEOMETRY_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'coordinates': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writeCoordinatesTextNode_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.POLYGON_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'outerBoundaryIs': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writeBoundaryIs_),
|
||||
'innerBoundaryIs': ol.xml.makeChildAppender(
|
||||
ol.format.KML.writeBoundaryIs_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.POLY_STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'color': ol.xml.makeChildAppender(ol.format.KML.writeColorTextNode_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Array.<string>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.STYLE_SEQUENCE_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, [
|
||||
'IconStyle', 'LabelStyle', 'LineStyle', 'PolyStyle'
|
||||
]);
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @type {Object.<string, Object.<string, ol.xml.Serializer>>}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.STYLE_SERIALIZERS_ = ol.xml.makeStructureNS(
|
||||
ol.format.KML.NAMESPACE_URIS_, {
|
||||
'IconStyle': ol.xml.makeChildAppender(ol.format.KML.writeIconStyle_),
|
||||
'LabelStyle': ol.xml.makeChildAppender(ol.format.KML.writeLabelStyle_),
|
||||
'LineStyle': ol.xml.makeChildAppender(ol.format.KML.writeLineStyle_),
|
||||
'PolyStyle': ol.xml.makeChildAppender(ol.format.KML.writePolyStyle_)
|
||||
});
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @param {string=} opt_nodeName Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.GX_NODE_FACTORY_ = function(value, objectStack, opt_nodeName) {
|
||||
return ol.xml.createElementNS(ol.format.KML.GX_NAMESPACE_URIS_[0],
|
||||
'gx:' + opt_nodeName);
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @param {string=} opt_nodeName Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.DOCUMENT_NODE_FACTORY_ = function(value, objectStack,
|
||||
opt_nodeName) {
|
||||
goog.asserts.assertInstanceof(value, ol.Feature);
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
goog.asserts.assert(ol.xml.isNode(parentNode));
|
||||
return ol.xml.createElementNS(parentNode.namespaceURI, 'Placemark');
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* @const
|
||||
* @param {*} value Value.
|
||||
* @param {Array.<*>} objectStack Object stack.
|
||||
* @param {string=} opt_nodeName Node name.
|
||||
* @return {Node|undefined} Node.
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.GEOMETRY_NODE_FACTORY_ = function(value, objectStack,
|
||||
opt_nodeName) {
|
||||
if (goog.isDefAndNotNull(value)) {
|
||||
goog.asserts.assertInstanceof(value, ol.geom.Geometry);
|
||||
var parentNode = objectStack[objectStack.length - 1].node;
|
||||
goog.asserts.assert(ol.xml.isNode(parentNode));
|
||||
return ol.xml.createElementNS(parentNode.namespaceURI,
|
||||
ol.format.KML.GEOMETRY_TYPE_TO_NODENAME_[value.getType()]);
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating coordinates nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.COLOR_NODE_FACTORY_ = ol.xml.makeSimpleNodeFactory('color');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating coordinates nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.COORDINATES_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('coordinates');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating innerBoundaryIs nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.INNER_BOUNDARY_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('innerBoundaryIs');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating Point nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.POINT_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('Point');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating LineString nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LINE_STRING_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('LineString');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating LinearRing nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.LINEAR_RING_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('LinearRing');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating Polygon nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.POLYGON_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('Polygon');
|
||||
|
||||
|
||||
/**
|
||||
* A factory for creating outerBoundaryIs nodes.
|
||||
* @const
|
||||
* @type {function(*, Array.<*>, string=): (Node|undefined)}
|
||||
* @private
|
||||
*/
|
||||
ol.format.KML.OUTER_BOUNDARY_NODE_FACTORY_ =
|
||||
ol.xml.makeSimpleNodeFactory('outerBoundaryIs');
|
||||
|
||||
|
||||
/**
|
||||
* Encode an array of features in the KML format.
|
||||
*
|
||||
* @function
|
||||
* @param {Array.<ol.Feature>} features Features.
|
||||
* @return {ArrayBuffer|Node|Object|string} Result.
|
||||
* @todo api
|
||||
*/
|
||||
ol.format.KML.prototype.writeFeatures;
|
||||
|
||||
|
||||
/**
|
||||
* @inheritDoc
|
||||
*/
|
||||
ol.format.KML.prototype.writeFeaturesNode = function(features) {
|
||||
var kml = ol.xml.createElementNS('http://earth.google.com/kml/2.2', 'kml');
|
||||
kml.setAttributeNS('http://www.w3.org/2000/xmlns/', 'xmlns:gx',
|
||||
ol.format.KML.GX_NAMESPACE_URIS_[0]);
|
||||
var /** @type {ol.xml.NodeStackItem} */ context = {node: kml};
|
||||
var properties = {};
|
||||
if (features.length > 1) {
|
||||
goog.object.set(properties, 'Document', features);
|
||||
} else if (features.length == 1) {
|
||||
goog.object.set(properties, 'Placemark', features[0]);
|
||||
}
|
||||
var orderedKeys = ol.format.KML.KML_SEQUENCE_[kml.namespaceURI];
|
||||
var values = ol.xml.makeSequence(properties, orderedKeys);
|
||||
ol.xml.pushSerializeAndPop(context, ol.format.KML.KML_SERIALIZERS_,
|
||||
ol.xml.OBJECT_PROPERTY_NODE_FACTORY, values, [], orderedKeys);
|
||||
return kml;
|
||||
};
|
||||
|
||||
Reference in New Issue
Block a user