loaders.gl
Version:
Framework-independent loaders for 3D graphics formats
813 lines (680 loc) • 23.5 kB
JavaScript
function _readOnlyError(name) { throw new Error("\"" + name + "\" is read-only"); }
function _classCallCheck(instance, Constructor) { if (!(instance instanceof Constructor)) { throw new TypeError("Cannot call a class as a function"); } }
function _defineProperties(target, props) { for (var i = 0; i < props.length; i++) { var descriptor = props[i]; descriptor.enumerable = descriptor.enumerable || false; descriptor.configurable = true; if ("value" in descriptor) descriptor.writable = true; Object.defineProperty(target, descriptor.key, descriptor); } }
function _createClass(Constructor, protoProps, staticProps) { if (protoProps) _defineProperties(Constructor.prototype, protoProps); if (staticProps) _defineProperties(Constructor, staticProps); return Constructor; }
/**
* Author - Nick Blackwell
* License - MIT
* Description - Defines a class, KMLParser which is a container for
* static kml parsing methods.
*/
/**
* KMLParser Class parses standard kml documents and returns objects
* representiong it's data.
* the optional transformations define the data within these objects,
* ie, documentTransform (for Geolive)
* will create a Layer object from its contents, and pull out the items
* which will be transformed aswell as MapItems.
*/
/* global console */
/* eslint-disable no-console */
var KMLParser =
/*#__PURE__*/
function () {
function KMLParser(xml) {
_classCallCheck(this, KMLParser);
this.kml = xml;
}
_createClass(KMLParser, [{
key: "parse",
value: function parse() {
return {
documents: this._filter(KMLParser.ParseDomDocuments(this.kml)),
folders: this._filter(KMLParser.ParseDomFolders(this.kml)),
markers: this._filter(KMLParser.ParseDomMarkers(this.kml)),
polygons: this._filter(KMLParser.ParseDomPolygons(this.kml)),
lines: this._filter(KMLParser.ParseDomLines(this.kml)),
overlays: this._filter(KMLParser.ParseDomGroundOverlays(this.kml)),
links: this._filter(KMLParser.ParseDomLinks(this.kml))
};
}
}, {
key: "parseDocuments",
value: function parseDocuments(callback) {
var _this = this;
var documentData = this._filter(KMLParser.ParseDomDocuments(this.kml));
documentData.forEach(function (p, i) {
return callback(p, _this.kml, documentData, i);
});
return this;
}
}, {
key: "parseFolders",
value: function parseFolders(callback) {
var _this2 = this;
var folderData = this._filter(KMLParser.ParseDomFolders(this.kml));
folderData.forEach(function (p, i) {
return callback(p, _this2.kml, folderData, i);
});
return this;
}
}, {
key: "parseMarkers",
value: function parseMarkers(callback) {
var _this3 = this;
var markerData = this._filter(KMLParser.ParseDomMarkers(this.kml));
markerData.forEach(function (p, i) {
return callback(p, _this3.kml, markerData, i);
});
return this;
}
}, {
key: "parsePolygons",
value: function parsePolygons(callback) {
var _this4 = this;
var polygonData = this._filter(KMLParser.ParseDomPolygons(this.kml));
polygonData.forEach(function (p, i) {
return callback(p, _this4.kml, polygonData, i);
});
return this;
}
}, {
key: "parseLines",
value: function parseLines(callback) {
var _this5 = this;
var lineData = this._filter(KMLParser.ParseDomLines(this.kml));
lineData.forEach(function (p, i) {
return callback(p, _this5.kml, lineData, i);
});
return this;
}
}, {
key: "parseGroundOverlays",
value: function parseGroundOverlays(callback) {
var _this6 = this;
var overlayData = this._filter(KMLParser.ParseDomGroundOverlays(this.kml));
overlayData.forEach(function (o, i) {
return callback(o, _this6.kml, overlayData, i);
});
return this;
}
}, {
key: "parseNetworklinks",
value: function parseNetworklinks(callback) {
var _this7 = this;
var linkData = this._filter(KMLParser.ParseDomLinks(this.kml));
linkData.forEach(function (p, i) {
return callback(p, _this7.kml, linkData, i);
});
return this;
}
}, {
key: "_filter",
value: function _filter(a) {
var _this8 = this;
var filtered = [];
if (this._filters && a && a.length) {
a.forEach(function (item) {
var bool = true;
_this8._filters.forEach(function (f) {
if (f(item) === false) {
bool = false;
}
});
if (bool) {
filtered.push(item);
}
});
return filtered;
}
return a;
}
}, {
key: "addFilter",
value: function addFilter(filter) {
if (!this._filters) {
this._filters = [];
}
this._filters.push(filter);
return this;
}
}], [{
key: "ParseDomDocuments",
value: function ParseDomDocuments(xmlDom) {
var docs = [];
var docsDomNodes = xmlDom.getElementsByTagName('Document');
for (var i = 0; i < docsDomNodes.length; i++) {
var node = docsDomNodes.item(i);
var docsData = Object.assign({}, KMLParser.ParseDomDoc(node), KMLParser.ParseNonSpatialDomData(node, {}));
var transform = function transform(options) {
return options;
};
docs.push(transform(docsData));
}
return docs;
}
}, {
key: "ParseDomDoc",
value: function ParseDomDoc(xmlDom) {
return {};
}
}, {
key: "ParseDomFolders",
value: function ParseDomFolders(xmlDom) {
var folders = [];
var folderDomNodes = KMLParser.ParseDomItems(xmlDom, 'Folder');
for (var i = 0; i < folderDomNodes.length; i++) {
var node = folderDomNodes[i];
var folderData = Object.assign({
type: 'folder'
}, KMLParser.ParseDomFolder(node), KMLParser.ParseNonSpatialDomData(node, {}));
var transform = function transform(options) {
return options;
};
folders.push(transform(folderData));
}
return folders;
}
}, {
key: "ParseDomLinks",
value: function ParseDomLinks(xmlDom) {
var links = [];
var linkDomNodes = xmlDom.getElementsByTagName('NetworkLink');
for (var i = 0; i < linkDomNodes.length; i++) {
var node = linkDomNodes.item(i);
var linkData = Object.assign({}, KMLParser.ParseDomLink(node), KMLParser.ParseNonSpatialDomData(node, {}));
var transform = function transform(options) {
return options;
};
links.push(transform(linkData));
}
return links;
}
}, {
key: "ParseDomFolder",
value: function ParseDomFolder(xmlDom) {
return {};
}
}, {
key: "ParseDomLink",
value: function ParseDomLink(xmlDom) {
var urls = xmlDom.getElementsByTagName('href');
var link = {
type: 'link'
};
if (urls.length > 0) {
var url = urls.item(0);
link.url = KMLParser.Value(url);
}
return link;
}
}, {
key: "ParseDomLines",
value: function ParseDomLines(xmlDom) {
var lines = [];
var lineDomNodes = KMLParser.ParseDomItems(xmlDom, 'LineString');
for (var i = 0; i < lineDomNodes.length; i++) {
var node = lineDomNodes[i];
var polygonData = Object.assign({
type: 'line',
lineColor: '#FF000000',
// black
lineWidth: 1,
polyColor: '#77000000',
// black semitransparent,
coordinates: KMLParser.ParseDomCoordinates(node) // returns an array of GLatLngs
}, KMLParser.ParseNonSpatialDomData(node, {}), KMLParser.ResolveDomStyle(KMLParser.ParseDomStyle(node), xmlDom));
var rgb = KMLParser.convertKMLColorToRGB(polygonData.lineColor);
polygonData.lineOpacity = rgb.opacity;
polygonData.lineColor = rgb.color;
lines.push(polygonData);
}
return lines;
}
}, {
key: "ParseDomGroundOverlays",
value: function ParseDomGroundOverlays(xmlDom) {
var lines = [];
var lineDomNodes = KMLParser.ParseDomItems(xmlDom, 'GroundOverlay');
for (var i = 0; i < lineDomNodes.length; i++) {
var node = lineDomNodes[i];
var polygonData = Object.assign({
type: 'imageoverlay',
icon: KMLParser.ParseDomIcon(node),
bounds: KMLParser.ParseDomBounds(node)
}, KMLParser.ParseNonSpatialDomData(node, {}));
lines.push(polygonData);
}
return lines;
}
}, {
key: "ParseDomPolygons",
value: function ParseDomPolygons(xmlDom) {
var polygons = [];
var polygonDomNodes = KMLParser.ParseDomItems(xmlDom, 'Polygon');
for (var i = 0; i < polygonDomNodes.length; i++) {
var node = polygonDomNodes[i];
var polygonData = Object.assign({
type: 'polygon',
fill: true,
lineColor: '#FF000000',
// black
lineWidth: 1,
polyColor: '#77000000',
// black semitransparent,
coordinates: KMLParser.ParseDomCoordinates(node) // returns an array of google.maps.LatLng
}, KMLParser.ParseNonSpatialDomData(node, {}), KMLParser.ResolveDomStyle(KMLParser.ParseDomStyle(node), xmlDom));
var lineRGB = KMLParser.convertKMLColorToRGB(polygonData.lineColor);
polygonData.lineOpacity = lineRGB.opacity;
polygonData.lineColor = lineRGB.color;
var polyRGB = KMLParser.convertKMLColorToRGB(polygonData.polyColor);
polygonData.polyOpacity = polygonData.fill ? polyRGB.opacity : 0;
polygonData.polyColor = polyRGB.color;
polygons.push(polygonData);
}
return polygons;
}
}, {
key: "ParseDomMarkers",
value: function ParseDomMarkers(xmlDom) {
var markers = [];
var markerDomNodes = KMLParser.ParseDomItems(xmlDom, 'Point');
for (var i = 0; i < markerDomNodes.length; i++) {
var node = markerDomNodes[i];
var coords = KMLParser.ParseDomCoordinates(node);
var marker = Object.assign({
type: 'point',
coordinates: coords[0] // returns an array of google.maps.LatLng
}, KMLParser.ParseNonSpatialDomData(node, {}));
var icon = KMLParser.ParseDomStyle(node);
if (icon.charAt(0) === '#') {
icon = KMLParser.ResolveDomStyle(icon, xmlDom).icon;
}
if (icon) {
// better to not have any hint of an icon (ie: icon:null) so default can be used by caller
marker.icon = icon;
}
markers.push(marker);
}
return markers;
}
}, {
key: "ParseDomCoordinates",
value: function ParseDomCoordinates(xmlDom) {
var coordNodes = xmlDom.getElementsByTagName('coordinates');
if (!coordNodes.length) {
console.warn(['KMLParser. DOM Node did not contain coordinates!', {
node: xmlDom
}]);
return null;
}
var node = coordNodes.item(0);
var s = KMLParser.Value(node);
s = s.trim();
var coordStrings = s.split(' ');
var coordinates = [];
Object.values(coordStrings).forEach(function (coord) {
var c = coord.split(',');
if (c.length > 1) {
// JSConsole([c[1],c[0]]);
coordinates.push([c[1], c[0]]);
}
});
return coordinates;
}
/* eslint-disable max-statements */
}, {
key: "ParseDomBounds",
value: function ParseDomBounds(xmlDom) {
var coordNodes = xmlDom.getElementsByTagName('LatLonBox');
if (!coordNodes.length) {
console.warn(['KMLParser. DOM Node did not contain coordinates!', {
node: xmlDom
}]);
return null;
}
var node = coordNodes.item(0);
var norths = node.getElementsByTagName('north');
var souths = node.getElementsByTagName('south');
var easts = node.getElementsByTagName('east');
var wests = node.getElementsByTagName('west');
var north = null;
var south = null;
var east = null;
var west = null;
if (!norths.length) {
console.warn(['KMLParser. DOM LatLngBox Node did not contain north!', {
node: xmlDom
}]);
} else {
north = parseFloat(KMLParser.Value(norths.item(0)));
}
if (!souths.length) {
console.warn(['KMLParser. DOM LatLngBox Node did not contain south!', {
node: xmlDom
}]);
} else {
south = parseFloat(KMLParser.Value(souths.item(0)));
}
if (!easts.length) {
console.warn(['KMLParser. DOM LatLngBox Node did not contain east!', {
node: xmlDom
}]);
} else {
east = parseFloat(KMLParser.Value(easts.item(0)));
}
if (!wests.length) {
console.warn(['KMLParser. DOM LatLngBox Node did not contain west!', {
node: xmlDom
}]);
} else {
west = parseFloat(KMLParser.Value(wests.item(0)));
}
return {
north: north,
south: south,
east: east,
west: west
};
}
/* eslint-enable max-statements */
}, {
key: "ParseNonSpatialDomData",
value: function ParseNonSpatialDomData(xmlDom, options) {
var config = Object.assign({}, {
maxOffset: 2
}, options);
var data = {
name: '',
description: null,
tags: {}
};
var names = xmlDom.getElementsByTagName('name');
for (var i = 0; i < names.length; i++) {
if (KMLParser.WithinOffsetDom(xmlDom, names.item(i), config.maxOffset)) {
data.name = KMLParser.Value(names.item(i));
break;
}
}
var descriptions = xmlDom.getElementsByTagName('description');
for (var _i = 0; _i < descriptions.length; _i++) {
if (KMLParser.WithinOffsetDom(xmlDom, descriptions.item(_i), config.maxOffset)) {
data.description = KMLParser.Value(descriptions.item(_i));
break;
}
}
if (xmlDom.hasAttribute('id')) {
data.id = parseInt(xmlDom.getAttribute('id'), 10);
}
var extendedDatas = xmlDom.getElementsByTagName('ExtendedData');
for (var _i2 = 0; _i2 < extendedDatas.length; _i2++) {
if (KMLParser.WithinOffsetDom(xmlDom, extendedDatas.item(_i2), config.maxOffset)) {
for (var j = 0; j < extendedDatas.item(_i2).childNodes.length; j++) {
var c = extendedDatas.item(_i2).childNodes.item(j);
var t = KMLParser.ParseTag(c);
if (t.name !== '#text') {
// eslint-disable-line
data.tags[t.name] = t.value;
}
}
}
}
return data;
}
}, {
key: "ParseTag",
value: function ParseTag(xmlDom) {
var tags = {
name: null,
value: {}
};
switch (xmlDom.nodeName) {
case 'Data':
case 'data':
// TODO: add data tags...
break;
case 'ID':
tags.name = 'ID';
tags.value = KMLParser.Value(xmlDom);
break;
default:
tags.name = xmlDom.nodeName;
tags.value = KMLParser.Value(xmlDom);
break;
}
return tags;
}
}, {
key: "WithinOffsetDom",
value: function WithinOffsetDom(parent, child, max) {
var current = child.parentNode;
for (var i = 0; i < max; i++) {
if (current.nodeName === (typeof parent === 'string' ? parent : parent.nodeName)) {
return true;
}
current = current.parentNode;
}
console.error(['KMLParser. Could not find parent node within expected bounds.', {
parentNode: parent,
childNode: child,
bounds: max
}]);
return false;
}
}, {
key: "ParseDomStyle",
value: function ParseDomStyle(xmlDom, options) {
var config = Object.assign({}, {
defaultStyle: 'default'
}, options);
var styles = xmlDom.getElementsByTagName('styleUrl');
var style = config.defaultStyle;
if (styles.length === 0) {
console.warn(['KMLParser. DOM Node did not contain styleUrl!', {
node: xmlDom,
options: config
}]);
} else {
var node = styles.item(0);
style = KMLParser.Value(node);
}
return style;
}
}, {
key: "ParseDomIcon",
value: function ParseDomIcon(xmlDom, options) {
var config = Object.assign({}, {
defaultIcon: false,
defaultScale: 1.0
}, options);
var icons = xmlDom.getElementsByTagName('Icon');
var icon = config.defaultStyle;
var scale = config.defaultScale;
if (icons.length === 0) {
console.warn(['KMLParser. DOM Node did not contain Icon!', {
node: xmlDom,
options: config
}]);
} else {
var node = icons.item(0);
var urls = node.getElementsByTagName('href');
if (urls.length === 0) {
console.warn(['KMLParser. DOM Icon Node did not contain href!', {
node: xmlDom,
options: config
}]);
} else {
var hrefNode = urls.item(0);
icon = KMLParser.Value(hrefNode);
}
var scales = node.getElementsByTagName('viewBoundScale');
if (scales.length === 0) {
console.warn(['KMLParser. DOM Icon Node did not contain viewBoundScale!', {
node: xmlDom,
options: config
}]);
} else {
var scaleNode = scales.item(0);
scale = parseFloat(KMLParser.Value(scaleNode));
}
}
return {
url: icon,
scale: scale
};
}
/* eslint-disable max-depth, max-statements */
}, {
key: "ResolveDomStyle",
value: function ResolveDomStyle(style, xmlDom) {
var data = {};
var name = style.charAt(0) === '#' ? style.substring(1, style.length) : style;
var styles = xmlDom.getElementsByTagName('Style');
for (var i = 0; i < styles.length; i++) {
var node = styles.item(i);
var id = node.getAttribute('id');
if (id === name) {
var lineStyles = node.getElementsByTagName('LineStyle');
var polyStyles = node.getElementsByTagName('PolyStyle');
var iconStyles = node.getElementsByTagName('href');
if (lineStyles.length > 0) {
var lineStyle = lineStyles.item(0);
var colors = lineStyle.getElementsByTagName('color');
if (colors.length > 0) {
var color = colors.item(0);
data.lineColor = KMLParser.Value(color);
}
var widths = lineStyle.getElementsByTagName('width');
if (widths.length > 0) {
var width = widths.item(0);
data.lineWidth = KMLParser.Value(width);
}
}
if (polyStyles.length > 0) {
var polyStyle = polyStyles.item(0);
var _colors = polyStyle.getElementsByTagName('color');
if (_colors.length > 0) {
var _color = _colors.item(0);
data.polyColor = KMLParser.Value(_color);
}
var outlines = polyStyle.getElementsByTagName('outline');
if (outlines.length > 0) {
var outline = outlines.item(0);
var o = KMLParser.Value(outline);
data.outline = Boolean(o);
}
}
if (iconStyles.length > 0) {
var iconStyle = iconStyles.item(0);
var icon = KMLParser.Value(iconStyle);
data.icon = icon;
}
}
}
return data;
}
/* eslint-enable max-depth, max-statements */
/* eslint-disable */
}, {
key: "ParseDomItems",
value: function ParseDomItems(xmlDom, tag) {
var tagName = tag || 'Point';
var items = [];
var markerDomNodes = xmlDom.getElementsByTagName(tagName);
for (var i = 0; i < markerDomNodes.length; i++) {
var node = markerDomNodes.item(i);
if (tag === 'GroundOverlay') {
items.push(node);
continue;
}
var parent = node.parentNode.nodeName === 'Placemark' ? node.parentNode : node.parentNode.parentNode.nodeName === 'Placemark' ? node.parentNode.parentNode : null;
if (parent === null) {
console.error(['Failed to find ParentNode for Element - ' + tagName, {
node: xmlDom
}]); // ();
} else {
items.push(parent);
}
}
return items;
} // KML Color is defined similar to RGB except it is in the opposite order and starts with opacity,
// #OOBBGGRR
}, {
key: "convertKMLColorToRGB",
value: function convertKMLColorToRGB(colorString) {
var colorStr = colorString.replace('#', '');
while (colorStr.length < 6) {
colorStr = (_readOnlyError("colorStr"), '0' + colorStr);
} // make sure line is dark!
while (colorStr.length < 8) {
colorStr = (_readOnlyError("colorStr"), 'F' + colorStr);
} // make sure opacity is a large fraction
if (colorStr.length > 8) {
colorStr = (_readOnlyError("colorStr"), colorStr.substring(0, 8));
}
var color = colorStr.substring(6, 8) + colorStr.substring(4, 6) + colorStr.substring(2, 4);
var opacity = parseInt(colorStr.substring(0, 2), 16) * 1.000 / parseInt('FF', 16);
var rgbVal = {
color: '#' + color,
opacity: opacity
};
return rgbVal;
}
}, {
key: "RGBColorToKML",
value: function RGBColorToKML(rgb, opacity) {
var colorStr = rgb.replace('#', '');
while (colorStr.length < 6) {
colorStr = (_readOnlyError("colorStr"), '0' + colorStr);
} //make sure line is dark!
if (colorStr.length > 6) {
colorStr = (_readOnlyError("colorStr"), colorStr.substring(0, 6));
}
if (opacity != null) {
if (opacity >= 0.0 && opacity <= 1.0) {
var _opacityNum = opacity;
} else if (parseInt(opacity) >= 0.0 && parseInt(opacity) <= 1.0) {
var _opacityNum2 = parseInt(opacity);
}
}
if (opacityNum === null) {
var _opacityNum3 = 1.0;
}
var opacityNum = opacityNum * 255.0;
var opacityStr = opacityNum.toString(16);
var kmlStr = opacityStr.substring(0, 2) + '' + colorStr.substring(4, 6) + colorStr.substring(2, 4) + colorStr.substring(0, 2);
return kmlStr;
}
}, {
key: "Value",
value: function Value(node) {
var value = node.nodeValue;
if (value) return value;
var str = '';
try {
if (node.childNodes && node.childNodes.length) {
Object.values(KMLParser.ChildNodesArray(node)).forEach(function (c) {
str += KMLParser.Value(c);
});
}
} catch (e) {
console.error(['SimpleKML Parser Exception', e]);
}
return str;
}
}, {
key: "ChildNodesArray",
value: function ChildNodesArray(node) {
var array = [];
if (node.childNodes && node.childNodes.length > 0) {
for (var i = 0; i < node.childNodes.length; i++) {
array.push(node.childNodes.item(i));
}
}
return array;
}
}]);
return KMLParser;
}();
export { KMLParser as default };
//# sourceMappingURL=kml-parser.js.map