loaders.gl: Add base format loaders + smartFetch (#670)

This commit is contained in:
Ib Green 2018-08-21 20:45:15 -07:00 committed by GitHub
parent f4009a6e83
commit 2f4f60bb7b
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
15 changed files with 266 additions and 100 deletions

20
modules/core/README.md Normal file
View File

@ -0,0 +1,20 @@
# luma.gl
<h1 align="center">luma.gl | <a href="https://uber.github.io/luma.gl">Docs</a></h1>
<h5 align="center">luma.gl: WebGL2 Components for Visualization</h5>
## Overview
luma.gl is a set of WebGL2 components for high-performance GPU-based rendering and computation in the browser.
It is the engine that powers applications and frameworks like
* [kepler.gl](https://github.com/uber/deck.gl) WebGL based visualization overlays
* [deck.gl](https://github.com/uber/deck.gl) WebGL based visualization overlays
# Installation, Running Examples etc
For details, please refer to the extensive [online website](https://uber.github.io/luma.gl).

View File

@ -0,0 +1,3 @@
# loaders.gl
This module contains framework independent 3D and geospatial loaders (parsers).

View File

@ -34,7 +34,7 @@
"lint-examples": "eslint examples",
"lint-yarn": "!(grep -q unpm.u yarn.lock) || (echo 'Please rebuild yarn.lock file using public npmrc' && false)",
"publish-prod": "npm run build && npm run test-fast && npm publish",
"publish-beta": "npm run build && npm run test-fast && npm publish --tag beta",
"publish-beta": "yarn run build && yarn run test-fast && npm publish --tag beta",
"bench": "node test/bench/node.js",
"bench-browser": "webpack-dev-server --config test/webpack.config.js --env.bench --progress --hot --open",
"test": "npm run lint && npm run test-node && npm run build && npm run test-dist && npm run collect-metrics && npm run test-browser-puppet",

View File

@ -0,0 +1,47 @@
import path from 'path';
export function smartFetch(url, loaders, options) {
/* global fetch */
return fetch(url)
.then(response => response.text())
.then(text => smartParse(text, url));
}
// Find a loader that works for extension/text
export function smartParse(text, url, loaders, options) {
const loader = getLoader(url, text, loaders);
if (!loader.parseText) {
throw new Error(`${loader.name} loader cannot handle text`);
}
return loader.parseText(text, options);
}
// Search the loaders array argument for a loader that matches extension or text
function getLoader(url, text, loaders) {
// Get extension without
let extension = path.extname(url) || url;
if (extension.length && extension[0] === '.') {
extension = extension.substr(1).toLowerCase();
}
for (const loader of loaders) {
if (loader.extension === extension) {
return loader;
}
}
for (const loader of loaders) {
if (loader.name.toLowerCase === extension) {
return loader;
}
}
for (const loader of loaders) {
if (loader.testText && loader.testText(text)) {
return loader;
}
}
return null;
}

View File

@ -0,0 +1,8 @@
import {csvParseRows} from 'd3-dsv';
export default {
name: 'CSV',
extension: 'csv',
testText: null,
parseText: csvParseRows
};

View File

@ -0,0 +1,11 @@
function parseText(text, options) {
return JSON.parse(text);
}
export default {
name: 'OBJ',
extension: 'obj',
testText: null,
parseText
};

View File

@ -0,0 +1,18 @@
import parseXML, {parseXMLSupported} from './parse-xml';
const XML_HEADER = '<?xml';
function testText(text) {
return text.startsWith(XML_HEADER);
}
export default {
name: 'KML',
extension: 'kml',
supported: parseXMLSupported(),
testText,
parseText: parseXML,
browserOnly: true,
worker: false
};

View File

@ -1,16 +1,26 @@
// UTILS
export {loadFile} from './common/loader';
export {loadUri} from './common/loader-utils/load-uri.js';
export {smartFetch, smartParse} from './common/smart-fetch';
// LOADERS
// GLB/GLTF LOADERS
export {default as GLBLoader} from './glb-loader/glb-loader';
// MODEL LOADERS
export {default as OBJLoader} from './obj-loader/obj-loader';
// POINT CLOUD LOADERS
export {default as PLYLoader} from './ply-loader/ply-loader';
export {default as LAZLoader} from './laz-loader/laz-loader';
// GEOSPATIAL LOADERS
export {default as KMLLoader} from './kml-loader/kml-loader';
// Extra exports
// GENERAL FORMAT LOADERS
export {default as JSONLoader} from './formats/json-loader/json-loader';
export {default as CSVLoader} from './formats/csv-loader/csv-loader';
export {default as XMLLoader} from './formats/xml-loader/xml-loader';
// EXPERIMENTAL EXPORTS
export {parseGLB, _GLBDecoder, _unpackGLBBuffers, _unpackJsonArrays} from './glb-loader';
export {encodeGLB, _GLBEncoder, _GLBBufferPacker, _packJsonArrays} from './glb-writer';

View File

@ -1,24 +1,31 @@
import KMLReader from './kml-reader';
import {parseXMLSupported} from './parse-xml';
import XMLLoader from '../formats/xml-loader/xml-loader';
import KMLParser from './kml-parser';
import normalizeKML from './kml-normalizer';
const KML_HEADER = `\
<?xml version="1.0" encoding="UTF-8"?>
<kml xmlns="http://www.opengis.net/kml/2.2">
`;
const DEFAULT_KML_OPTIONS = {
normalize: true
};
function testText(text) {
return text.startsWith(KML_HEADER);
}
function parseText(text) {
const kmlLoader = new KMLReader(text);
return kmlLoader.parse();
function parseText(text, options = DEFAULT_KML_OPTIONS) {
const xml = XMLLoader.parseText(text);
const kmlLoader = new KMLParser(xml);
const kml = kmlLoader.parse();
return options.normalize ? normalizeKML(kml) : kml;
}
export default {
name: 'KML',
extension: 'kml',
supported: parseXMLSupported(),
supported: XMLLoader.supported,
testText,
parseText,
browserOnly: true,

View File

@ -0,0 +1,22 @@
export default function normalizeKML(kml) {
// Convert coordinates to [lng, lat, z] format
for (const key in kml) {
for (const item of kml[key]) {
normalizeKMLItem(item, key);
}
}
return kml;
}
// Normalizes coordinates to lng/lat format
function normalizeKMLItem(item) {
if (item.coordinates && item.coordinates.length) {
if (Array.isArray(item.coordinates[0])) {
item.coordinates = item.coordinates.map(([lat, lng, z = 0]) => [lng, lat, z]);
} else {
// Marker coordinates are just a single coord (not an array of coords)
const [lat, lng, z = 0] = item.coordinates;
item.coordinates = [lng, lat, z];
}
}
}

View File

@ -1,12 +1,12 @@
/**
* Author - Nick Blackwell
* License - MIT
* Description - Defines a class, KmlReader which is a container for
* Description - Defines a class, KMLParser which is a container for
* static kml parsing methods.
*/
/**
* KmlReader Class parses standard kml documents and returns objects
* 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)
@ -17,67 +17,62 @@
/* global console */
/* eslint-disable no-console */
import parseXML from './parse-xml';
export default class KMLParser {
export default class KmlReader {
constructor(kml) {
this.kml = kml;
if (typeof kml === 'string') {
this.kml = parseXML(kml);
}
constructor(xml) {
this.kml = xml;
}
parse() {
return {
documents: this._filter(KmlReader.ParseDomDocuments(this.kml)),
folders: this._filter(KmlReader.ParseDomFolders(this.kml)),
markers: this._filter(KmlReader.ParseDomMarkers(this.kml)),
polygons: this._filter(KmlReader.ParseDomPolygons(this.kml)),
lines: this._filter(KmlReader.ParseDomLines(this.kml)),
overlays: this._filter(KmlReader.ParseDomGroundOverlays(this.kml)),
links: this._filter(KmlReader.ParseDomLinks(this.kml))
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))
};
}
parseDocuments(callback) {
const documentData = this._filter(KmlReader.ParseDomDocuments(this.kml));
const documentData = this._filter(KMLParser.ParseDomDocuments(this.kml));
documentData.forEach((p, i) => callback(p, this.kml, documentData, i));
return this;
}
parseFolders(callback) {
const folderData = this._filter(KmlReader.ParseDomFolders(this.kml));
const folderData = this._filter(KMLParser.ParseDomFolders(this.kml));
folderData.forEach((p, i) => callback(p, this.kml, folderData, i));
return this;
}
parseMarkers(callback) {
const markerData = this._filter(KmlReader.ParseDomMarkers(this.kml));
const markerData = this._filter(KMLParser.ParseDomMarkers(this.kml));
markerData.forEach((p, i) => callback(p, this.kml, markerData, i));
return this;
}
parsePolygons(callback) {
const polygonData = this._filter(KmlReader.ParseDomPolygons(this.kml));
const polygonData = this._filter(KMLParser.ParseDomPolygons(this.kml));
polygonData.forEach((p, i) => callback(p, this.kml, polygonData, i));
return this;
}
parseLines(callback) {
const lineData = this._filter(KmlReader.ParseDomLines(this.kml));
const lineData = this._filter(KMLParser.ParseDomLines(this.kml));
lineData.forEach((p, i) => callback(p, this.kml, lineData, i));
return this;
}
parseGroundOverlays(callback) {
const overlayData = this._filter(KmlReader.ParseDomGroundOverlays(this.kml));
const overlayData = this._filter(KMLParser.ParseDomGroundOverlays(this.kml));
overlayData.forEach((o, i) => callback(o, this.kml, overlayData, i));
return this;
}
parseNetworklinks(callback) {
const linkData = this._filter(KmlReader.ParseDomLinks(this.kml));
const linkData = this._filter(KMLParser.ParseDomLinks(this.kml));
linkData.forEach((p, i) => callback(p, this.kml, linkData, i));
return this;
}
@ -117,8 +112,8 @@ export default class KmlReader {
const node = docsDomNodes.item(i);
const docsData = Object.assign(
{},
KmlReader.ParseDomDoc(node),
KmlReader.ParseNonSpatialDomData(node, {})
KMLParser.ParseDomDoc(node),
KMLParser.ParseNonSpatialDomData(node, {})
);
const transform = options => options;
@ -133,15 +128,15 @@ export default class KmlReader {
static ParseDomFolders(xmlDom) {
const folders = [];
const folderDomNodes = KmlReader.ParseDomItems(xmlDom, 'Folder');
const folderDomNodes = KMLParser.ParseDomItems(xmlDom, 'Folder');
for (let i = 0; i < folderDomNodes.length; i++) {
const node = folderDomNodes[i];
const folderData = Object.assign(
{
type: 'folder'
},
KmlReader.ParseDomFolder(node),
KmlReader.ParseNonSpatialDomData(node, {})
KMLParser.ParseDomFolder(node),
KMLParser.ParseNonSpatialDomData(node, {})
);
const transform = options => options;
@ -156,8 +151,8 @@ export default class KmlReader {
for (let i = 0; i < linkDomNodes.length; i++) {
const node = linkDomNodes.item(i);
const linkData = Object.assign({},
KmlReader.ParseDomLink(node),
KmlReader.ParseNonSpatialDomData(node, {})
KMLParser.ParseDomLink(node),
KMLParser.ParseNonSpatialDomData(node, {})
);
const transform = options => options;
@ -178,14 +173,14 @@ export default class KmlReader {
};
if (urls.length > 0) {
const url = urls.item(0);
link.url = KmlReader.Value(url);
link.url = KMLParser.Value(url);
}
return link;
}
static ParseDomLines(xmlDom) {
const lines = [];
const lineDomNodes = KmlReader.ParseDomItems(xmlDom, 'LineString');
const lineDomNodes = KMLParser.ParseDomItems(xmlDom, 'LineString');
for (let i = 0; i < lineDomNodes.length; i++) {
const node = lineDomNodes[i];
@ -196,13 +191,13 @@ export default class KmlReader {
lineColor: '#FF000000', // black
lineWidth: 1,
polyColor: '#77000000', // black semitransparent,
coordinates: KmlReader.ParseDomCoordinates(node) // returns an array of GLatLngs
coordinates: KMLParser.ParseDomCoordinates(node) // returns an array of GLatLngs
},
KmlReader.ParseNonSpatialDomData(node, {}),
KmlReader.ResolveDomStyle(KmlReader.ParseDomStyle(node), xmlDom)
KMLParser.ParseNonSpatialDomData(node, {}),
KMLParser.ResolveDomStyle(KMLParser.ParseDomStyle(node), xmlDom)
);
const rgb = KmlReader.convertKMLColorToRGB(polygonData.lineColor);
const rgb = KMLParser.convertKMLColorToRGB(polygonData.lineColor);
polygonData.lineOpacity = rgb.opacity;
polygonData.lineColor = rgb.color;
@ -214,7 +209,7 @@ export default class KmlReader {
static ParseDomGroundOverlays(xmlDom) {
const lines = [];
const lineDomNodes = KmlReader.ParseDomItems(xmlDom, 'GroundOverlay');
const lineDomNodes = KMLParser.ParseDomItems(xmlDom, 'GroundOverlay');
for (let i = 0; i < lineDomNodes.length; i++) {
const node = lineDomNodes[i];
@ -222,10 +217,10 @@ export default class KmlReader {
const polygonData = Object.assign(
{
type: 'imageoverlay',
icon: KmlReader.ParseDomIcon(node),
bounds: KmlReader.ParseDomBounds(node)
icon: KMLParser.ParseDomIcon(node),
bounds: KMLParser.ParseDomBounds(node)
},
KmlReader.ParseNonSpatialDomData(node, {})
KMLParser.ParseNonSpatialDomData(node, {})
);
lines.push(polygonData);
@ -236,7 +231,7 @@ export default class KmlReader {
static ParseDomPolygons(xmlDom) {
const polygons = [];
const polygonDomNodes = KmlReader.ParseDomItems(xmlDom, 'Polygon');
const polygonDomNodes = KMLParser.ParseDomItems(xmlDom, 'Polygon');
for (let i = 0; i < polygonDomNodes.length; i++) {
@ -249,18 +244,18 @@ export default class KmlReader {
lineColor: '#FF000000', // black
lineWidth: 1,
polyColor: '#77000000', // black semitransparent,
coordinates: KmlReader.ParseDomCoordinates(node) // returns an array of google.maps.LatLng
coordinates: KMLParser.ParseDomCoordinates(node) // returns an array of google.maps.LatLng
},
KmlReader.ParseNonSpatialDomData(node, {}),
KmlReader.ResolveDomStyle(KmlReader.ParseDomStyle(node), xmlDom)
KMLParser.ParseNonSpatialDomData(node, {}),
KMLParser.ResolveDomStyle(KMLParser.ParseDomStyle(node), xmlDom)
);
const lineRGB = KmlReader.convertKMLColorToRGB(polygonData.lineColor);
const lineRGB = KMLParser.convertKMLColorToRGB(polygonData.lineColor);
polygonData.lineOpacity = lineRGB.opacity;
polygonData.lineColor = lineRGB.color;
const polyRGB = KmlReader.convertKMLColorToRGB(polygonData.polyColor);
const polyRGB = KMLParser.convertKMLColorToRGB(polygonData.polyColor);
polygonData.polyOpacity = (polygonData.fill) ? polyRGB.opacity : 0;
polygonData.polyColor = polyRGB.color;
@ -272,22 +267,22 @@ export default class KmlReader {
static ParseDomMarkers(xmlDom) {
const markers = [];
const markerDomNodes = KmlReader.ParseDomItems(xmlDom, 'Point');
const markerDomNodes = KMLParser.ParseDomItems(xmlDom, 'Point');
for (let i = 0; i < markerDomNodes.length; i++) {
const node = markerDomNodes[i];
const coords = KmlReader.ParseDomCoordinates(node);
const coords = KMLParser.ParseDomCoordinates(node);
const marker = Object.assign(
{
type: 'point',
coordinates: coords[0] // returns an array of google.maps.LatLng
},
KmlReader.ParseNonSpatialDomData(node, {})
KMLParser.ParseNonSpatialDomData(node, {})
);
let icon = KmlReader.ParseDomStyle(node);
let icon = KMLParser.ParseDomStyle(node);
if (icon.charAt(0) === '#') {
icon = KmlReader.ResolveDomStyle(icon, xmlDom).icon;
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
@ -301,13 +296,13 @@ export default class KmlReader {
static ParseDomCoordinates(xmlDom) {
const coordNodes = xmlDom.getElementsByTagName('coordinates');
if (!coordNodes.length) {
console.warn(['KmlReader. DOM Node did not contain coordinates!', {
console.warn(['KMLParser. DOM Node did not contain coordinates!', {
node: xmlDom
}]);
return null;
}
const node = coordNodes.item(0);
let s = KmlReader.Value(node);
let s = KMLParser.Value(node);
s = s.trim();
const coordStrings = s.split(' ');
const coordinates = [];
@ -326,7 +321,7 @@ export default class KmlReader {
static ParseDomBounds(xmlDom) {
const coordNodes = xmlDom.getElementsByTagName('LatLonBox');
if (!coordNodes.length) {
console.warn(['KmlReader. DOM Node did not contain coordinates!', {
console.warn(['KMLParser. DOM Node did not contain coordinates!', {
node: xmlDom
}]);
return null;
@ -343,32 +338,32 @@ export default class KmlReader {
let west = null;
if (!norths.length) {
console.warn(['KmlReader. DOM LatLngBox Node did not contain north!', {
console.warn(['KMLParser. DOM LatLngBox Node did not contain north!', {
node: xmlDom
}]);
} else {
north = parseFloat(KmlReader.Value(norths.item(0)));
north = parseFloat(KMLParser.Value(norths.item(0)));
}
if (!souths.length) {
console.warn(['KmlReader. DOM LatLngBox Node did not contain south!', {
console.warn(['KMLParser. DOM LatLngBox Node did not contain south!', {
node: xmlDom
}]);
} else {
south = parseFloat(KmlReader.Value(souths.item(0)));
south = parseFloat(KMLParser.Value(souths.item(0)));
}
if (!easts.length) {
console.warn(['KmlReader. DOM LatLngBox Node did not contain east!', {
console.warn(['KMLParser. DOM LatLngBox Node did not contain east!', {
node: xmlDom
}]);
} else {
east = parseFloat(KmlReader.Value(easts.item(0)));
east = parseFloat(KMLParser.Value(easts.item(0)));
}
if (!wests.length) {
console.warn(['KmlReader. DOM LatLngBox Node did not contain west!', {
console.warn(['KMLParser. DOM LatLngBox Node did not contain west!', {
node: xmlDom
}]);
} else {
west = parseFloat(KmlReader.Value(wests.item(0)));
west = parseFloat(KMLParser.Value(wests.item(0)));
}
return {
north,
@ -392,16 +387,16 @@ export default class KmlReader {
const names = xmlDom.getElementsByTagName('name');
for (let i = 0; i < names.length; i++) {
if (KmlReader.WithinOffsetDom(xmlDom, names.item(i), config.maxOffset)) {
data.name = (KmlReader.Value(names.item(i)));
if (KMLParser.WithinOffsetDom(xmlDom, names.item(i), config.maxOffset)) {
data.name = (KMLParser.Value(names.item(i)));
break;
}
}
const descriptions = xmlDom.getElementsByTagName('description');
for (let i = 0; i < descriptions.length; i++) {
if (KmlReader.WithinOffsetDom(xmlDom, descriptions.item(i), config.maxOffset)) {
data.description = (KmlReader.Value(descriptions.item(i)));
if (KMLParser.WithinOffsetDom(xmlDom, descriptions.item(i), config.maxOffset)) {
data.description = (KMLParser.Value(descriptions.item(i)));
break;
}
}
@ -412,10 +407,10 @@ export default class KmlReader {
const extendedDatas = xmlDom.getElementsByTagName('ExtendedData');
for (let i = 0; i < extendedDatas.length; i++) {
if (KmlReader.WithinOffsetDom(xmlDom, extendedDatas.item(i), config.maxOffset)) {
if (KMLParser.WithinOffsetDom(xmlDom, extendedDatas.item(i), config.maxOffset)) {
for (let j = 0; j < extendedDatas.item(i).childNodes.length; j++) {
const c = extendedDatas.item(i).childNodes.item(j);
const t = KmlReader.ParseTag(c);
const t = KMLParser.ParseTag(c);
if (t.name !== '#text') { // eslint-disable-line
data.tags[t.name] = t.value;
}
@ -438,11 +433,11 @@ export default class KmlReader {
break;
case 'ID':
tags.name = 'ID';
tags.value = KmlReader.Value(xmlDom);
tags.value = KMLParser.Value(xmlDom);
break;
default:
tags.name = xmlDom.nodeName;
tags.value = KmlReader.Value(xmlDom);
tags.value = KMLParser.Value(xmlDom);
break;
}
@ -457,7 +452,7 @@ export default class KmlReader {
}
current = current.parentNode;
}
console.error(['KmlReader. Could not find parent node within expected bounds.', {
console.error(['KMLParser. Could not find parent node within expected bounds.', {
parentNode: parent,
childNode: child,
bounds: max
@ -474,13 +469,13 @@ export default class KmlReader {
const styles = xmlDom.getElementsByTagName('styleUrl');
let style = config.defaultStyle;
if (styles.length === 0) {
console.warn(['KmlReader. DOM Node did not contain styleUrl!', {
console.warn(['KMLParser. DOM Node did not contain styleUrl!', {
node: xmlDom,
options: config
}]);
} else {
const node = styles.item(0);
style = (KmlReader.Value(node));
style = (KMLParser.Value(node));
}
return style;
}
@ -496,7 +491,7 @@ export default class KmlReader {
let icon = config.defaultStyle;
let scale = config.defaultScale;
if (icons.length === 0) {
console.warn(['KmlReader. DOM Node did not contain Icon!', {
console.warn(['KMLParser. DOM Node did not contain Icon!', {
node: xmlDom,
options: config
}]);
@ -504,25 +499,25 @@ export default class KmlReader {
const node = icons.item(0);
const urls = node.getElementsByTagName('href');
if (urls.length === 0) {
console.warn(['KmlReader. DOM Icon Node did not contain href!', {
console.warn(['KMLParser. DOM Icon Node did not contain href!', {
node: xmlDom,
options: config
}]);
} else {
const hrefNode = urls.item(0);
icon = (KmlReader.Value(hrefNode));
icon = (KMLParser.Value(hrefNode));
}
const scales = node.getElementsByTagName('viewBoundScale');
if (scales.length === 0) {
console.warn(['KmlReader. DOM Icon Node did not contain viewBoundScale!', {
console.warn(['KMLParser. DOM Icon Node did not contain viewBoundScale!', {
node: xmlDom,
options: config
}]);
} else {
const scaleNode = scales.item(0);
scale = parseFloat(KmlReader.Value(scaleNode));
scale = parseFloat(KMLParser.Value(scaleNode));
}
}
return {
@ -549,12 +544,12 @@ export default class KmlReader {
const colors = lineStyle.getElementsByTagName('color');
if (colors.length > 0) {
const color = colors.item(0);
data.lineColor = KmlReader.Value(color);
data.lineColor = KMLParser.Value(color);
}
const widths = lineStyle.getElementsByTagName('width');
if (widths.length > 0) {
const width = widths.item(0);
data.lineWidth = KmlReader.Value(width);
data.lineWidth = KMLParser.Value(width);
}
}
if (polyStyles.length > 0) {
@ -562,18 +557,18 @@ export default class KmlReader {
const colors = polyStyle.getElementsByTagName('color');
if (colors.length > 0) {
const color = colors.item(0);
data.polyColor = KmlReader.Value(color);
data.polyColor = KMLParser.Value(color);
}
const outlines = polyStyle.getElementsByTagName('outline');
if (outlines.length > 0) {
const outline = outlines.item(0);
const o = KmlReader.Value(outline);
const o = KMLParser.Value(outline);
data.outline = Boolean(o);
}
}
if (iconStyles.length > 0) {
const iconStyle = iconStyles.item(0);
const icon = KmlReader.Value(iconStyle);
const icon = KMLParser.Value(iconStyle);
data.icon = icon;
}
}
@ -671,8 +666,8 @@ export default class KmlReader {
let str = '';
try {
if (node.childNodes && node.childNodes.length) {
Object.values(KmlReader.ChildNodesArray(node)).forEach(c => {
str += KmlReader.Value(c);
Object.values(KMLParser.ChildNodesArray(node)).forEach(c => {
str += KMLParser.Value(c);
});
}
} catch (e) {

View File

@ -1 +1,2 @@
import './loader-utils';
import './smart-fetch.spec';

View File

@ -0,0 +1,28 @@
/* eslint-disable max-len */
import test from 'tape-catch';
import {OBJLoader, KMLLoader, smartParse} from 'loaders.gl';
import KML from '../kml-loader/KML_Samples.kml';
const LOADERS = [
OBJLoader, KMLLoader
];
test('smartFetch', t => {
if (!KMLLoader.supported) {
t.comment('XML parsing not available');
} else {
const data = smartParse(KML, 'KML_Samples.kml', LOADERS);
t.equal(data.documents.length, 2, 'Documents were found');
t.equal(data.markers.length, 4, 'Markers were found');
t.equal(data.lines.length, 6, 'Lines were found');
t.equal(data.polygons.length, 9, 'Polygons were found');
t.equal(data.overlays.length, 1, 'Overlay was found');
for (const key in data) {
for (const object of data[key]) {
t.comment(`${key}: ${JSON.stringify(object)}`);
}
}
}
t.end();
});

View File

@ -2599,10 +2599,6 @@ domutils@1.5.1:
dom-serializer "0"
domelementtype "1"
draco3d@^1.3.3:
version "1.3.3"
resolved "https://registry.yarnpkg.com/draco3d/-/draco3d-1.3.3.tgz#cf1c32f83fb95863089f907b8dcc1683657eb6dc"
duplexer3@^0.1.4:
version "0.1.4"
resolved "https://registry.yarnpkg.com/duplexer3/-/duplexer3-0.1.4.tgz#ee01dd1cac0ed3cbc7fdbea37dc0a8f1ce002ce2"