UNPKG

terriajs

Version:

Geospatial data visualization platform.

266 lines (210 loc) 7.94 kB
'use strict'; /*global require*/ var defined = require('terriajs-cesium/Source/Core/defined'); var RuntimeError = require('terriajs-cesium/Source/Core/RuntimeError'); var gmlNamespace = 'http://www.opengis.net/gml'; /** * Converts a GML v3.1.1 simple features document to GeoJSON. * @param {Document|String} xml The GML document. * @return {Object} The GeoJSON object. */ function gmlToGeoJson(xml) { if (typeof xml === 'string') { var parser = new DOMParser(); xml = parser.parseFromString(xml, 'text/xml'); } var result = []; var featureCollection = xml.documentElement; var featureMembers = featureCollection.getElementsByTagNameNS(gmlNamespace, 'featureMember'); for (var featureIndex = 0; featureIndex < featureMembers.length; ++featureIndex) { var featureMember = featureMembers[featureIndex]; var properties = {}; getGmlPropertiesRecursively(featureMember, properties); var feature = { type: 'Feature', geometry: getGmlGeometry(featureMember), properties: properties }; if (defined(feature.geometry)) { result.push(feature); } } return { type: 'FeatureCollection', crs: { type: 'EPSG', properties: { code: '4326' } }, features: result }; } var gmlSimpleFeatureNames = [ 'Curve', 'LineString', 'Point', 'Polygon', 'MultiCurve', 'MultPoint', 'MultiSurface', 'Surface' ]; function getGmlPropertiesRecursively(gmlNode, properties) { var isSingleValue = true; for (var i = 0; i < gmlNode.childNodes.length; ++i) { var child = gmlNode.childNodes[i]; if (child.nodeType === Node.ELEMENT_NODE) { isSingleValue = false; } if (gmlSimpleFeatureNames.indexOf(child.localName) >= 0) { continue; } if (child.hasChildNodes() && getGmlPropertiesRecursively(child, properties)) { properties[child.localName] = child.textContent; } } return isSingleValue; } function getGmlGeometry(gmlNode) { var result; for (var i = 0; !defined(result) && i < gmlNode.childNodes.length; ++i) { var child = gmlNode.childNodes[i]; if (gmlSimpleFeatureNames.indexOf(child.localName) >= 0) { return createGeoJsonGeometryFeatureFromGmlGeometry(child); } else { result = getGmlGeometry(child); } } return result; } function createLineStringFromGmlGeometry(geometry) { var coordinates = []; var posNodes = geometry.getElementsByTagNameNS(gmlNamespace, 'posList'); for (var i = 0; i < posNodes.length; ++i) { var positions = gml2coord(posNodes[i].textContent); for (var j = 0; j < positions.length; ++j) { coordinates.push(positions[j]); } } return { type: 'LineString', coordinates: coordinates }; } function createPointFromGmlGeometry(geometry) { var posNodes = geometry.getElementsByTagNameNS(gmlNamespace, 'pos'); if (posNodes < 1) { throw new RuntimeError('GML point element is missing a pos element.'); } return { type: 'Point', coordinates: gml2coord(posNodes[0].textContent)[0] }; } function createMultiLineStringFromGmlGeometry(geometry) { var curveMembers = geometry.getElementsByTagNameNS(gmlNamespace, 'posList'); var curves = []; for (var i = 0; i < curveMembers.length; ++i) { curves.push(gml2coord(curveMembers[i].textContent)); } return { type: 'MultiLineString', coordinates: curves }; } function createMultiPolygonFromGmlGeomtry(geometry) { var coordinates = []; var polygons = geometry.getElementsByTagNameNS(gmlNamespace, 'Polygon'); for (var i = 0; i < polygons.length; ++i) { var polygon = polygons[i]; var exteriorNodes = polygon.getElementsByTagNameNS(gmlNamespace, 'exterior'); if (exteriorNodes.length < 1) { throw new RuntimeError('GML polygon is missing its exterior ring.'); } var polygonCoordinates = []; var exterior = exteriorNodes[0]; var posListNodes = exterior.getElementsByTagNameNS(gmlNamespace, 'posList'); if (posListNodes.length < 1) { throw new RuntimeError('GML polygon\'s exterior ring is missing a posList.'); } polygonCoordinates.push(gml2coord(posListNodes[0].textContent)); var interiors = polygon.getElementsByTagNameNS(gmlNamespace, 'interior'); for (var j = 0; j < interiors.length; ++j) { var interior = interiors[j]; var interiorPosListNodes = interior.getElementsByTagNameNS(gmlNamespace, 'posList'); if (interiorPosListNodes.length < 1) { continue; } polygonCoordinates.push(gml2coord(interiorPosListNodes[0].textContent)); } coordinates.push(polygonCoordinates); } return { type: 'MultiPolygon', coordinates: coordinates }; } function createPolygonFromGmlGeometry(geometry) { var polygonCoordinates = []; var exteriorNodes = geometry.getElementsByTagNameNS(gmlNamespace, 'exterior'); if (exteriorNodes.length < 1) { throw new RuntimeError('GML polygon is missing its exterior ring.'); } var exterior = exteriorNodes[0]; var posListNodes = exterior.getElementsByTagNameNS(gmlNamespace, 'posList'); if (posListNodes.length < 1) { throw new RuntimeError('GML polygon\'s exterior ring is missing a posList.'); } polygonCoordinates.push(gml2coord(posListNodes[0].textContent)); var interiors = geometry.getElementsByTagNameNS(gmlNamespace, 'interior'); for (var j = 0; j < interiors.length; ++j) { var interior = interiors[j]; var interiorPosListNodes = interior.getElementsByTagNameNS(gmlNamespace, 'posList'); if (interiorPosListNodes.length < 1) { continue; } polygonCoordinates.push(gml2coord(interiorPosListNodes[0].textContent)); } return { type: 'Polygon', coordinates: polygonCoordinates }; } function createMultiPointFromGmlGeometry(geometry) { var posNodes = geometry.getElementsByTagNameNS(gmlNamespace, 'pos'); var coordinates = []; for (var i = 0; i < posNodes.length; ++i) { coordinates.push(gml2coord(posNodes[i].textContent)[0]); } return { type: 'MultiPoint', coordinates: coordinates }; } var featureCreators = { Curve: createLineStringFromGmlGeometry, LineString: createLineStringFromGmlGeometry, Point: createPointFromGmlGeometry, Polygon: createPolygonFromGmlGeometry, MultiCurve: createMultiLineStringFromGmlGeometry, MultPoint: createMultiPointFromGmlGeometry, MultiSurface: createMultiPolygonFromGmlGeomtry, Surface: createPolygonFromGmlGeometry }; function createGeoJsonGeometryFeatureFromGmlGeometry(geometry) { var type = geometry.localName; var creator = featureCreators[type]; if (!defined(creator)) { throw new RuntimeError('GML contains unsupported feature type: ' + type); } return creator(geometry); } function isNotEmpty(s) { return s.length !== 0; } //Utility function to change esri gml positions to geojson positions function gml2coord(posList) { var pnts = posList.split(/[ ,]+/).filter(isNotEmpty); var coords = []; for (var i = 0; i < pnts.length; i+=2) { coords.push([parseFloat(pnts[i+1]), parseFloat(pnts[i])]); } return coords; } module.exports = gmlToGeoJson;