UNPKG

node-red-contrib-tak-registration

Version:

A Node-RED node to register to TAK and to help wrap files as datapackages to send to TAK

399 lines (366 loc) 11.7 kB
import Coordinate from '../geom/Coordinate' import GeometryFactory from '../geom/GeometryFactory' const regExes = { 'typeStr': /^\s*(\w+)\s*\(\s*(.*)\s*\)\s*$/, 'emptyTypeStr': /^\s*(\w+)\s*EMPTY\s*$/, 'spaces': /\s+/, 'parenComma': /\)\s*,\s*\(/, 'doubleParenComma': /\)\s*\)\s*,\s*\(\s*\(/, // can't use {2} here 'trimParens': /^\s*\(?(.*?)\)?\s*$/ } /** * Class for reading and writing Well-Known Text. * * NOTE: Adapted from OpenLayers 2.11 implementation. */ /** Create a new parser for WKT * * @param {GeometryFactory} geometryFactory * @return An instance of WKTParser. * @constructor * @private */ export default class WKTParser { constructor (geometryFactory) { this.geometryFactory = geometryFactory || new GeometryFactory() } /** * Deserialize a WKT string and return a geometry. Supports WKT for POINT, * MULTIPOINT, LINESTRING, LINEARRING, MULTILINESTRING, POLYGON, MULTIPOLYGON, * and GEOMETRYCOLLECTION. * * @param {String} wkt A WKT string. * @return {Geometry} A geometry instance. * @private */ read (wkt) { var geometry, type, str wkt = wkt.replace(/[\n\r]/g, ' ') var matches = regExes.typeStr.exec(wkt) if (wkt.search('EMPTY') !== -1) { matches = regExes.emptyTypeStr.exec(wkt) matches[2] = undefined } if (matches) { type = matches[1].toLowerCase() str = matches[2] if (parse[type]) { geometry = parse[type].apply(this, [str]) } } if (geometry === undefined) throw new Error('Could not parse WKT ' + wkt) return geometry } /** * Serialize a geometry into a WKT string. * * @param {Geometry} geometry A feature or array of features. * @return {String} The WKT string representation of the input geometries. * @private */ write (geometry) { return this.extractGeometry(geometry) } /** * Entry point to construct the WKT for a single Geometry object. * * @param {Geometry} geometry * @return {String} A WKT string of representing the geometry. * @private */ extractGeometry (geometry) { var type = geometry.getGeometryType().toLowerCase() if (!extract[type]) { return null } var wktType = type.toUpperCase() var data if (geometry.isEmpty()) { data = wktType + ' EMPTY' } else { data = wktType + '(' + extract[type].apply(this, [geometry]) + ')' } return data } } /** * Object with properties corresponding to the geometry types. Property values * are functions that do the actual data extraction. * @private */ const extract = { coordinate (coordinate) { return coordinate.x + ' ' + coordinate.y }, /** * Return a space delimited string of point coordinates. * * @param {Point} * point * @return {String} A string of coordinates representing the point. */ point (point) { return extract.coordinate.call(this, point._coordinates._coordinates[0]) }, /** * Return a comma delimited string of point coordinates from a multipoint. * * @param {MultiPoint} * multipoint * @return {String} A string of point coordinate strings representing the * multipoint. */ multipoint (multipoint) { var array = [] for (let i = 0, len = multipoint._geometries.length; i < len; ++i) { array.push('(' + extract.point.apply(this, [multipoint._geometries[i]]) + ')') } return array.join(',') }, /** * Return a comma delimited string of point coordinates from a line. * * @param {LineString} linestring * @return {String} A string of point coordinate strings representing the linestring. */ linestring (linestring) { var array = [] for (let i = 0, len = linestring._points._coordinates.length; i < len; ++i) { array.push(extract.coordinate.apply(this, [linestring._points._coordinates[i]])) } return array.join(',') }, linearring (linearring) { var array = [] for (let i = 0, len = linearring._points._coordinates.length; i < len; ++i) { array.push(extract.coordinate.apply(this, [linearring._points._coordinates[i]])) } return array.join(',') }, /** * Return a comma delimited string of linestring strings from a * multilinestring. * * @param {MultiLineString} multilinestring * @return {String} A string of of linestring strings representing the multilinestring. */ multilinestring (multilinestring) { var array = [] for (let i = 0, len = multilinestring._geometries.length; i < len; ++i) { array.push('(' + extract.linestring.apply(this, [multilinestring._geometries[i]]) + ')') } return array.join(',') }, /** * Return a comma delimited string of linear ring arrays from a polygon. * * @param {Polygon} polygon * @return {String} An array of linear ring arrays representing the polygon. */ polygon (polygon) { var array = [] array.push('(' + extract.linestring.apply(this, [polygon._shell]) + ')') for (let i = 0, len = polygon._holes.length; i < len; ++i) { array.push('(' + extract.linestring.apply(this, [polygon._holes[i]]) + ')') } return array.join(',') }, /** * Return an array of polygon arrays from a multipolygon. * * @param {MultiPolygon} multipolygon * @return {String} An array of polygon arrays representing the multipolygon. */ multipolygon (multipolygon) { var array = [] for (let i = 0, len = multipolygon._geometries.length; i < len; ++i) { array.push('(' + extract.polygon.apply(this, [multipolygon._geometries[i]]) + ')') } return array.join(',') }, /** * Return the WKT portion between 'GEOMETRYCOLLECTION(' and ')' for an * geometrycollection. * * @param {GeometryCollection} collection * @return {String} internal WKT representation of the collection. */ geometrycollection (collection) { var array = [] for (let i = 0, len = collection._geometries.length; i < len; ++i) { array.push(this.extractGeometry(collection._geometries[i])) } return array.join(',') } } /** * Object with properties corresponding to the geometry types. Property values * are functions that do the actual parsing. * @private */ const parse = { /** * Return point geometry given a point WKT fragment. * * @param {String} str A WKT fragment representing the point. * @return {Point} A point geometry. * @private */ point (str) { if (str === undefined) { return this.geometryFactory.createPoint() } var coords = str.trim().split(regExes.spaces) return this.geometryFactory.createPoint(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) }, /** * Return a multipoint geometry given a multipoint WKT fragment. * * @param {String} str A WKT fragment representing the multipoint. * @return {Point} A multipoint feature. * @private */ multipoint (str) { if (str === undefined) { return this.geometryFactory.createMultiPoint() } var point var points = str.trim().split(',') var components = [] for (let i = 0, len = points.length; i < len; ++i) { point = points[i].replace(regExes.trimParens, '$1') components.push(parse.point.apply(this, [point])) } return this.geometryFactory.createMultiPoint(components) }, /** * Return a linestring geometry given a linestring WKT fragment. * * @param {String} str A WKT fragment representing the linestring. * @return {LineString} A linestring geometry. * @private */ linestring (str) { if (str === undefined) { return this.geometryFactory.createLineString() } var points = str.trim().split(',') var components = [] var coords for (let i = 0, len = points.length; i < len; ++i) { coords = points[i].trim().split(regExes.spaces) components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) } return this.geometryFactory.createLineString(components) }, /** * Return a linearring geometry given a linearring WKT fragment. * * @param {String} str A WKT fragment representing the linearring. * @return {LinearRing} A linearring geometry. * @private */ linearring (str) { if (str === undefined) { return this.geometryFactory.createLinearRing() } var points = str.trim().split(',') var components = [] var coords for (let i = 0, len = points.length; i < len; ++i) { coords = points[i].trim().split(regExes.spaces) components.push(new Coordinate(Number.parseFloat(coords[0]), Number.parseFloat(coords[1]))) } return this.geometryFactory.createLinearRing(components) }, /** * Return a multilinestring geometry given a multilinestring WKT fragment. * * @param {String} str A WKT fragment representing the multilinestring. * @return {MultiLineString} A multilinestring geometry. * @private */ multilinestring (str) { if (str === undefined) { return this.geometryFactory.createMultiLineString() } var line var lines = str.trim().split(regExes.parenComma) var components = [] for (let i = 0, len = lines.length; i < len; ++i) { line = lines[i].replace(regExes.trimParens, '$1') components.push(parse.linestring.apply(this, [line])) } return this.geometryFactory.createMultiLineString(components) }, /** * Return a polygon geometry given a polygon WKT fragment. * * @param {String} str A WKT fragment representing the polygon. * @return {Polygon} A polygon geometry. * @private */ polygon (str) { if (str === undefined) { return this.geometryFactory.createPolygon() } var ring, linestring, linearring var rings = str.trim().split(regExes.parenComma) var shell var holes = [] for (let i = 0, len = rings.length; i < len; ++i) { ring = rings[i].replace(regExes.trimParens, '$1') linestring = parse.linestring.apply(this, [ring]) linearring = this.geometryFactory.createLinearRing(linestring._points) if (i === 0) { shell = linearring } else { holes.push(linearring) } } return this.geometryFactory.createPolygon(shell, holes) }, /** * Return a multipolygon geometry given a multipolygon WKT fragment. * * @param {String} str A WKT fragment representing the multipolygon. * @return {MultiPolygon} A multipolygon geometry. * @private */ multipolygon (str) { if (str === undefined) { return this.geometryFactory.createMultiPolygon() } var polygon var polygons = str.trim().split(regExes.doubleParenComma) var components = [] for (let i = 0, len = polygons.length; i < len; ++i) { polygon = polygons[i].replace(regExes.trimParens, '$1') components.push(parse.polygon.apply(this, [polygon])) } return this.geometryFactory.createMultiPolygon(components) }, /** * Return a geometrycollection given a geometrycollection WKT fragment. * * @param {String} str A WKT fragment representing the geometrycollection. * @return {GeometryCollection} * @private */ geometrycollection (str) { if (str === undefined) { return this.geometryFactory.createGeometryCollection() } // separate components of the collection with | str = str.replace(/,\s*([A-Za-z])/g, '|$1') var wktArray = str.trim().split('|') var components = [] for (let i = 0, len = wktArray.length; i < len; ++i) { components.push(this.read(wktArray[i])) } return this.geometryFactory.createGeometryCollection(components) } }