UNPKG

c8y-openlayer

Version:

This module is designed to help integrate Openlayer with Cumulocity IoT

432 lines (370 loc) 11.5 kB
//FIXME Implement projection handling import _ol_ from '../index.js'; import _ol_asserts_ from '../asserts.js'; import _ol_ext_PBF_ from 'pbf'; import _ol_format_Feature_ from '../format/feature.js'; import _ol_format_FormatType_ from '../format/formattype.js'; import _ol_geom_GeometryLayout_ from '../geom/geometrylayout.js'; import _ol_geom_GeometryType_ from '../geom/geometrytype.js'; import _ol_geom_LineString_ from '../geom/linestring.js'; import _ol_geom_MultiLineString_ from '../geom/multilinestring.js'; import _ol_geom_MultiPoint_ from '../geom/multipoint.js'; import _ol_geom_MultiPolygon_ from '../geom/multipolygon.js'; import _ol_geom_Point_ from '../geom/point.js'; import _ol_geom_Polygon_ from '../geom/polygon.js'; import _ol_geom_flat_orient_ from '../geom/flat/orient.js'; import _ol_proj_Projection_ from '../proj/projection.js'; import _ol_proj_Units_ from '../proj/units.js'; import _ol_render_Feature_ from '../render/feature.js'; /** * @classdesc * Feature format for reading data in the Mapbox MVT format. * * @constructor * @extends {ol.format.Feature} * @param {olx.format.MVTOptions=} opt_options Options. * @api */ var _ol_format_MVT_ = function(opt_options) { _ol_format_Feature_.call(this); var options = opt_options ? opt_options : {}; /** * @type {ol.proj.Projection} */ this.defaultDataProjection = new _ol_proj_Projection_({ code: 'EPSG:3857', units: _ol_proj_Units_.TILE_PIXELS }); /** * @private * @type {function((ol.geom.Geometry|Object.<string,*>)=)| * function(ol.geom.GeometryType,Array.<number>, * (Array.<number>|Array.<Array.<number>>),Object.<string,*>,number)} */ this.featureClass_ = options.featureClass ? options.featureClass : _ol_render_Feature_; /** * @private * @type {string|undefined} */ this.geometryName_ = options.geometryName; /** * @private * @type {string} */ this.layerName_ = options.layerName ? options.layerName : 'layer'; /** * @private * @type {Array.<string>} */ this.layers_ = options.layers ? options.layers : null; /** * @private * @type {ol.Extent} */ this.extent_ = null; }; _ol_.inherits(_ol_format_MVT_, _ol_format_Feature_); /** * Reader callbacks for parsing the PBF. * @type {Object.<string, function(number, Object, ol.ext.PBF)>} */ _ol_format_MVT_.pbfReaders_ = { layers: function(tag, layers, pbf) { if (tag === 3) { var layer = { keys: [], values: [], features: [] }; var end = pbf.readVarint() + pbf.pos; pbf.readFields(_ol_format_MVT_.pbfReaders_.layer, layer, end); layer.length = layer.features.length; if (layer.length) { layers[layer.name] = layer; } } }, layer: function(tag, layer, pbf) { if (tag === 15) { layer.version = pbf.readVarint(); } else if (tag === 1) { layer.name = pbf.readString(); } else if (tag === 5) { layer.extent = pbf.readVarint(); } else if (tag === 2) { layer.features.push(pbf.pos); } else if (tag === 3) { layer.keys.push(pbf.readString()); } else if (tag === 4) { var value = null; var end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { tag = pbf.readVarint() >> 3; value = tag === 1 ? pbf.readString() : tag === 2 ? pbf.readFloat() : tag === 3 ? pbf.readDouble() : tag === 4 ? pbf.readVarint64() : tag === 5 ? pbf.readVarint() : tag === 6 ? pbf.readSVarint() : tag === 7 ? pbf.readBoolean() : null; } layer.values.push(value); } }, feature: function(tag, feature, pbf) { if (tag == 1) { feature.id = pbf.readVarint(); } else if (tag == 2) { var end = pbf.readVarint() + pbf.pos; while (pbf.pos < end) { var key = feature.layer.keys[pbf.readVarint()]; var value = feature.layer.values[pbf.readVarint()]; feature.properties[key] = value; } } else if (tag == 3) { feature.type = pbf.readVarint(); } else if (tag == 4) { feature.geometry = pbf.pos; } } }; /** * Read a raw feature from the pbf offset stored at index `i` in the raw layer. * @suppress {missingProperties} * @private * @param {ol.ext.PBF} pbf PBF. * @param {Object} layer Raw layer. * @param {number} i Index of the feature in the raw layer's `features` array. * @return {Object} Raw feature. */ _ol_format_MVT_.readRawFeature_ = function(pbf, layer, i) { pbf.pos = layer.features[i]; var end = pbf.readVarint() + pbf.pos; var feature = { layer: layer, type: 0, properties: {} }; pbf.readFields(_ol_format_MVT_.pbfReaders_.feature, feature, end); return feature; }; /** * Read the raw geometry from the pbf offset stored in a raw feature's geometry * proeprty. * @suppress {missingProperties} * @private * @param {ol.ext.PBF} pbf PBF. * @param {Object} feature Raw feature. * @param {Array.<number>} flatCoordinates Array to store flat coordinates in. * @param {Array.<number>} ends Array to store ends in. */ _ol_format_MVT_.readRawGeometry_ = function(pbf, feature, flatCoordinates, ends) { pbf.pos = feature.geometry; var end = pbf.readVarint() + pbf.pos; var cmd = 1; var length = 0; var x = 0; var y = 0; var coordsLen = 0; var currentEnd = 0; while (pbf.pos < end) { if (!length) { var cmdLen = pbf.readVarint(); cmd = cmdLen & 0x7; length = cmdLen >> 3; } length--; if (cmd === 1 || cmd === 2) { x += pbf.readSVarint(); y += pbf.readSVarint(); if (cmd === 1) { // moveTo if (coordsLen > currentEnd) { ends.push(coordsLen); currentEnd = coordsLen; } } flatCoordinates.push(x, y); coordsLen += 2; } else if (cmd === 7) { if (coordsLen > currentEnd) { // close polygon flatCoordinates.push( flatCoordinates[currentEnd], flatCoordinates[currentEnd + 1]); coordsLen += 2; } } else { _ol_asserts_.assert(false, 59); // Invalid command found in the PBF } } if (coordsLen > currentEnd) { ends.push(coordsLen); currentEnd = coordsLen; } }; /** * @suppress {missingProperties} * @private * @param {number} type The raw feature's geometry type * @param {number} numEnds Number of ends of the flat coordinates of the * geometry. * @return {ol.geom.GeometryType} The geometry type. */ _ol_format_MVT_.getGeometryType_ = function(type, numEnds) { /** @type {ol.geom.GeometryType} */ var geometryType; if (type === 1) { geometryType = numEnds === 1 ? _ol_geom_GeometryType_.POINT : _ol_geom_GeometryType_.MULTI_POINT; } else if (type === 2) { geometryType = numEnds === 1 ? _ol_geom_GeometryType_.LINE_STRING : _ol_geom_GeometryType_.MULTI_LINE_STRING; } else if (type === 3) { geometryType = _ol_geom_GeometryType_.POLYGON; // MultiPolygon not relevant for rendering - winding order determines // outer rings of polygons. } return geometryType; }; /** * @private * @param {ol.ext.PBF} pbf PBF * @param {Object} rawFeature Raw Mapbox feature. * @param {olx.format.ReadOptions=} opt_options Read options. * @return {ol.Feature|ol.render.Feature} Feature. */ _ol_format_MVT_.prototype.createFeature_ = function(pbf, rawFeature, opt_options) { var type = rawFeature.type; if (type === 0) { return null; } var feature; var id = rawFeature.id; var values = rawFeature.properties; values[this.layerName_] = rawFeature.layer.name; var flatCoordinates = []; var ends = []; _ol_format_MVT_.readRawGeometry_(pbf, rawFeature, flatCoordinates, ends); var geometryType = _ol_format_MVT_.getGeometryType_(type, ends.length); if (this.featureClass_ === _ol_render_Feature_) { feature = new this.featureClass_(geometryType, flatCoordinates, ends, values, id); } else { var geom; if (geometryType == _ol_geom_GeometryType_.POLYGON) { var endss = []; var offset = 0; var prevEndIndex = 0; for (var i = 0, ii = ends.length; i < ii; ++i) { var end = ends[i]; if (!_ol_geom_flat_orient_.linearRingIsClockwise(flatCoordinates, offset, end, 2)) { endss.push(ends.slice(prevEndIndex, i)); prevEndIndex = i; } offset = end; } if (endss.length > 1) { ends = endss; geom = new _ol_geom_MultiPolygon_(null); } else { geom = new _ol_geom_Polygon_(null); } } else { geom = geometryType === _ol_geom_GeometryType_.POINT ? new _ol_geom_Point_(null) : geometryType === _ol_geom_GeometryType_.LINE_STRING ? new _ol_geom_LineString_(null) : geometryType === _ol_geom_GeometryType_.POLYGON ? new _ol_geom_Polygon_(null) : geometryType === _ol_geom_GeometryType_.MULTI_POINT ? new _ol_geom_MultiPoint_ (null) : geometryType === _ol_geom_GeometryType_.MULTI_LINE_STRING ? new _ol_geom_MultiLineString_(null) : null; } geom.setFlatCoordinates(_ol_geom_GeometryLayout_.XY, flatCoordinates, ends); feature = new this.featureClass_(); if (this.geometryName_) { feature.setGeometryName(this.geometryName_); } var geometry = _ol_format_Feature_.transformWithOptions(geom, false, this.adaptOptions(opt_options)); feature.setGeometry(geometry); feature.setId(id); feature.setProperties(values); } return feature; }; /** * @inheritDoc * @api */ _ol_format_MVT_.prototype.getLastExtent = function() { return this.extent_; }; /** * @inheritDoc */ _ol_format_MVT_.prototype.getType = function() { return _ol_format_FormatType_.ARRAY_BUFFER; }; /** * @inheritDoc * @api */ _ol_format_MVT_.prototype.readFeatures = function(source, opt_options) { var layers = this.layers_; var pbf = new _ol_ext_PBF_(/** @type {ArrayBuffer} */ (source)); var pbfLayers = pbf.readFields(_ol_format_MVT_.pbfReaders_.layers, {}); /** @type {Array.<ol.Feature|ol.render.Feature>} */ var features = []; var pbfLayer; for (var name in pbfLayers) { if (layers && layers.indexOf(name) == -1) { continue; } pbfLayer = pbfLayers[name]; var rawFeature; for (var i = 0, ii = pbfLayer.length; i < ii; ++i) { rawFeature = _ol_format_MVT_.readRawFeature_(pbf, pbfLayer, i); features.push(this.createFeature_(pbf, rawFeature)); } this.extent_ = pbfLayer ? [0, 0, pbfLayer.extent, pbfLayer.extent] : null; } return features; }; /** * @inheritDoc * @api */ _ol_format_MVT_.prototype.readProjection = function(source) { return this.defaultDataProjection; }; /** * Sets the layers that features will be read from. * @param {Array.<string>} layers Layers. * @api */ _ol_format_MVT_.prototype.setLayers = function(layers) { this.layers_ = layers; }; /** * Not implemented. * @override */ _ol_format_MVT_.prototype.readFeature = function() {}; /** * Not implemented. * @override */ _ol_format_MVT_.prototype.readGeometry = function() {}; /** * Not implemented. * @override */ _ol_format_MVT_.prototype.writeFeature = function() {}; /** * Not implemented. * @override */ _ol_format_MVT_.prototype.writeGeometry = function() {}; /** * Not implemented. * @override */ _ol_format_MVT_.prototype.writeFeatures = function() {}; export default _ol_format_MVT_;