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
440 lines (402 loc) • 11.3 kB
JavaScript
import Coordinate from '../geom/Coordinate'
import GeometryFactory from '../geom/GeometryFactory'
const geometryTypes = ['Point', 'MultiPoint', 'LineString', 'MultiLineString', 'Polygon', 'MultiPolygon']
/**
* Class for reading and writing Well-Known Text.Create a new parser for GeoJSON
* NOTE: Adapted from OpenLayers 2.11 implementation.
*/
/**
* Create a new parser for GeoJSON
*
* @param {GeometryFactory} geometryFactory
* @return An instance of GeoJsonParser.
* @constructor
* @private
*/
export default class GeoJSONParser {
constructor (geometryFactory) {
this.geometryFactory = geometryFactory || new GeometryFactory()
}
/**
* Deserialize a GeoJSON object and return the Geometry or Feature(Collection) with JSTS Geometries
*
* @param {}
* A GeoJSON object.
* @return {} A Geometry instance or object representing a Feature(Collection) with Geometry instances.
* @private
*/
read (json) {
let obj
if (typeof json === 'string') {
obj = JSON.parse(json)
} else {
obj = json
}
const type = obj.type
if (!parse[type]) {
throw new Error('Unknown GeoJSON type: ' + obj.type)
}
if (geometryTypes.indexOf(type) !== -1) {
return parse[type].apply(this, [obj.coordinates])
} else if (type === 'GeometryCollection') {
return parse[type].apply(this, [obj.geometries])
}
// feature or feature collection
return parse[type].apply(this, [obj])
}
/**
* Serialize a Geometry object into GeoJSON
*
* @param {Geometry}
* geometry A Geometry or array of Geometries.
* @return {Object} A GeoJSON object represting the input Geometry/Geometries.
* @private
*/
write (geometry) {
const type = geometry.getGeometryType()
if (!extract[type]) {
throw new Error('Geometry is not supported')
}
return extract[type].apply(this, [geometry])
}
}
const parse = {
/**
* Parse a GeoJSON Feature object
*
* @param {Object}
* obj Object to parse.
*
* @return {Object} Feature with geometry/bbox converted to JSTS Geometries.
*/
Feature: function (obj) {
const feature = {}
// copy features
for (let key in obj) {
feature[key] = obj[key]
}
// parse geometry
if (obj.geometry) {
const type = obj.geometry.type
if (!parse[type]) {
throw new Error('Unknown GeoJSON type: ' + obj.type)
}
feature.geometry = this.read(obj.geometry)
}
// bbox
if (obj.bbox) {
feature.bbox = parse.bbox.apply(this, [obj.bbox])
}
return feature
},
/**
* Parse a GeoJSON FeatureCollection object
*
* @param {Object}
* obj Object to parse.
*
* @return {Object} FeatureCollection with geometry/bbox converted to JSTS Geometries.
*/
FeatureCollection: function (obj) {
const featureCollection = {}
if (obj.features) {
featureCollection.features = []
for (let i = 0; i < obj.features.length; ++i) {
featureCollection.features.push(this.read(obj.features[i]))
}
}
if (obj.bbox) {
featureCollection.bbox = this.parse.bbox.apply(this, [obj.bbox])
}
return featureCollection
},
/**
* Convert the ordinates in an array to an array of Coordinates
*
* @param {Array}
* array Array with {Number}s.
*
* @return {Array} Array with Coordinates.
*/
coordinates: function (array) {
const coordinates = []
for (let i = 0; i < array.length; ++i) {
const sub = array[i]
coordinates.push(new Coordinate(sub[0], sub[1]))
}
return coordinates
},
/**
* Convert the bbox to a LinearRing
*
* @param {Array}
* array Array with [xMin, yMin, xMax, yMax].
*
* @return {Array} Array with Coordinates.
*/
bbox: function (array) {
return this.geometryFactory.createLinearRing([
new Coordinate(array[0], array[1]),
new Coordinate(array[2], array[1]),
new Coordinate(array[2], array[3]),
new Coordinate(array[0], array[3]),
new Coordinate(array[0], array[1])
])
},
/**
* Convert an Array with ordinates to a Point
*
* @param {Array}
* array Array with ordinates.
*
* @return {Point} Point.
*/
Point: function (array) {
const coordinate = new Coordinate(array[0], array[1])
return this.geometryFactory.createPoint(coordinate)
},
/**
* Convert an Array with coordinates to a MultiPoint
*
* @param {Array}
* array Array with coordinates.
*
* @return {MultiPoint} MultiPoint.
*/
MultiPoint: function (array) {
const points = []
for (let i = 0; i < array.length; ++i) {
points.push(parse.Point.apply(this, [array[i]]))
}
return this.geometryFactory.createMultiPoint(points)
},
/**
* Convert an Array with coordinates to a LineString
*
* @param {Array}
* array Array with coordinates.
*
* @return {LineString} LineString.
*/
LineString: function (array) {
const coordinates = parse.coordinates.apply(this, [array])
return this.geometryFactory.createLineString(coordinates)
},
/**
* Convert an Array with coordinates to a MultiLineString
*
* @param {Array}
* array Array with coordinates.
*
* @return {MultiLineString} MultiLineString.
*/
MultiLineString: function (array) {
const lineStrings = []
for (let i = 0; i < array.length; ++i) {
lineStrings.push(parse.LineString.apply(this, [array[i]]))
}
return this.geometryFactory.createMultiLineString(lineStrings)
},
/**
* Convert an Array to a Polygon
*
* @param {Array}
* array Array with shell and holes.
*
* @return {Polygon} Polygon.
*/
Polygon: function (array) {
const shellCoordinates = parse.coordinates.apply(this, [array[0]])
const shell = this.geometryFactory.createLinearRing(shellCoordinates)
const holes = []
for (let i = 1; i < array.length; ++i) {
var hole = array[i]
var coordinates = parse.coordinates.apply(this, [hole])
var linearRing = this.geometryFactory.createLinearRing(coordinates)
holes.push(linearRing)
}
return this.geometryFactory.createPolygon(shell, holes)
},
/**
* Convert an Array to a MultiPolygon
*
* @param {Array}
* array Array of arrays with shell and rings.
*
* @return {MultiPolygon} MultiPolygon.
*/
MultiPolygon: function (array) {
const polygons = []
for (let i = 0; i < array.length; ++i) {
const polygon = array[i]
polygons.push(parse.Polygon.apply(this, [polygon]))
}
return this.geometryFactory.createMultiPolygon(polygons)
},
/**
* Convert an Array to a GeometryCollection
*
* @param {Array}
* array Array of GeoJSON geometries.
*
* @return {GeometryCollection} GeometryCollection.
*/
GeometryCollection: function (array) {
const geometries = []
for (let i = 0; i < array.length; ++i) {
const geometry = array[i]
geometries.push(this.read(geometry))
}
return this.geometryFactory.createGeometryCollection(geometries)
}
}
const extract = {
/**
* Convert a Coordinate to an Array
*
* @param {Coordinate}
* coordinate Coordinate to convert.
*
* @return {Array} Array of ordinates.
*/
coordinate: function (coordinate) {
return [coordinate.x, coordinate.y]
},
/**
* Convert a Point to a GeoJSON object
*
* @param {Point}
* point Point to convert.
*
* @return {Array} Array of 2 ordinates (paired to a coordinate).
*/
Point: function (point) {
const array = extract.coordinate.apply(this, [point.getCoordinate()])
return {
type: 'Point',
coordinates: array
}
},
/**
* Convert a MultiPoint to a GeoJSON object
*
* @param {MultiPoint}
* multipoint MultiPoint to convert.
*
* @return {Array} Array of coordinates.
*/
MultiPoint: function (multipoint) {
const array = []
for (let i = 0; i < multipoint._geometries.length; ++i) {
const point = multipoint._geometries[i]
const geoJson = extract.Point.apply(this, [point])
array.push(geoJson.coordinates)
}
return {
type: 'MultiPoint',
coordinates: array
}
},
/**
* Convert a LineString to a GeoJSON object
*
* @param {LineString}
* linestring LineString to convert.
*
* @return {Array} Array of coordinates.
*/
LineString: function (linestring) {
const array = []
const coordinates = linestring.getCoordinates()
for (let i = 0; i < coordinates.length; ++i) {
const coordinate = coordinates[i]
array.push(extract.coordinate.apply(this, [coordinate]))
}
return {
type: 'LineString',
coordinates: array
}
},
/**
* Convert a MultiLineString to a GeoJSON object
*
* @param {MultiLineString}
* multilinestring MultiLineString to convert.
*
* @return {Array} Array of Array of coordinates.
*/
MultiLineString: function (multilinestring) {
const array = []
for (let i = 0; i < multilinestring._geometries.length; ++i) {
const linestring = multilinestring._geometries[i]
const geoJson = extract.LineString.apply(this, [linestring])
array.push(geoJson.coordinates)
}
return {
type: 'MultiLineString',
coordinates: array
}
},
/**
* Convert a Polygon to a GeoJSON object
*
* @param {Polygon}
* polygon Polygon to convert.
*
* @return {Array} Array with shell, holes.
*/
Polygon: function (polygon) {
const array = []
const shellGeoJson = extract.LineString.apply(this, [polygon._shell])
array.push(shellGeoJson.coordinates)
for (let i = 0; i < polygon._holes.length; ++i) {
const hole = polygon._holes[i]
const holeGeoJson = extract.LineString.apply(this, [hole])
array.push(holeGeoJson.coordinates)
}
return {
type: 'Polygon',
coordinates: array
}
},
/**
* Convert a MultiPolygon to a GeoJSON object
*
* @param {MultiPolygon}
* multipolygon MultiPolygon to convert.
*
* @return {Array} Array of polygons.
*/
MultiPolygon: function (multipolygon) {
const array = []
for (let i = 0; i < multipolygon._geometries.length; ++i) {
const polygon = multipolygon._geometries[i]
const geoJson = extract.Polygon.apply(this, [polygon])
array.push(geoJson.coordinates)
}
return {
type: 'MultiPolygon',
coordinates: array
}
},
/**
* Convert a GeometryCollection to a GeoJSON object
*
* @param {GeometryCollection}
* collection GeometryCollection to convert.
*
* @return {Array} Array of geometries.
*/
GeometryCollection: function (collection) {
const array = []
for (let i = 0; i < collection._geometries.length; ++i) {
const geometry = collection._geometries[i]
const type = geometry.getGeometryType()
array.push(extract[type].apply(this, [geometry]))
}
return {
type: 'GeometryCollection',
geometries: array
}
}
}