From 598111b78ecf45667fcb4b929c61f30e49b9cbbe Mon Sep 17 00:00:00 2001 From: Andreas Hocevar Date: Tue, 13 Oct 2015 14:18:00 +0200 Subject: [PATCH] Introduce ol.format.MVT --- externs/olx.js | 34 ++++ package.json | 6 +- src/ol/featureloader.js | 7 +- src/ol/format/featureformat.js | 2 +- src/ol/format/format.js | 1 + src/ol/format/mvtformat.js | 196 ++++++++++++++++++++++ test/spec/ol/data/14-8938-5680.vector.pbf | Bin 0 -> 46937 bytes test/spec/ol/format/mvtformat.test.js | 68 ++++++++ 8 files changed, 311 insertions(+), 3 deletions(-) create mode 100644 src/ol/format/mvtformat.js create mode 100644 test/spec/ol/data/14-8938-5680.vector.pbf create mode 100644 test/spec/ol/format/mvtformat.test.js diff --git a/externs/olx.js b/externs/olx.js index eef86f69d0..57986ca413 100644 --- a/externs/olx.js +++ b/externs/olx.js @@ -1685,6 +1685,40 @@ olx.format.EsriJSONOptions; olx.format.EsriJSONOptions.prototype.geometryName; +/** + * @typedef {{geometryName: (string|undefined), + * layers: (Array.|undefined), + * layerName: (string|undefined)}} + * @api + */ +olx.format.MVTOptions; + + +/** + * Geometry name to use when creating features. Default is 'geometry'. + * @type {string|undefined} + * @api + */ +olx.format.MVTOptions.prototype.geometryName; + + +/** + * Name of the feature attribute that holds the layer name. Default is 'layer'. + * @type {string|undefined} + * @api + */ +olx.format.MVTOptions.prototype.layerName; + + +/** + * Layers to read features from. If not provided, features will be read from all + * layers. + * @type {Array.|undefined} + * @api + */ +olx.format.MVTOptions.prototype.layers; + + /** * @typedef {{factor: (number|undefined), * geometryLayout: (ol.geom.GeometryLayout|undefined)}} diff --git a/package.json b/package.json index bf323b85ae..20c1e81495 100644 --- a/package.json +++ b/package.json @@ -38,9 +38,11 @@ "metalsmith": "1.6.0", "metalsmith-templates": "0.7.0", "nomnom": "1.8.0", + "pbf": "1.3.5", "pixelworks": "1.0.0", "rbush": "1.3.5", "temp": "0.8.1", + "vector-tile": "1.1.3", "walk": "2.3.4" }, "devDependencies": { @@ -64,6 +66,8 @@ }, "ext": [ "rbush", - {"module": "pixelworks", "browserify": true} + {"module": "pbf", "browserify": true}, + {"module": "pixelworks", "browserify": true}, + {"module": "vector-tile", "name": "vectortile", "browserify": true} ] } diff --git a/src/ol/featureloader.js b/src/ol/featureloader.js index 0450108f19..735ca5b67f 100644 --- a/src/ol/featureloader.js +++ b/src/ol/featureloader.js @@ -61,7 +61,10 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success) { */ function(extent, resolution, projection) { var xhrIo = new goog.net.XhrIo(); - xhrIo.setResponseType(goog.net.XhrIo.ResponseType.TEXT); + xhrIo.setResponseType( + format.getType() == ol.format.FormatType.ARRAY_BUFFER ? + goog.net.XhrIo.ResponseType.ARRAY_BUFFER : + goog.net.XhrIo.ResponseType.TEXT); goog.events.listen(xhrIo, goog.net.EventType.COMPLETE, /** * @param {Event} event Event. @@ -87,6 +90,8 @@ ol.featureloader.loadFeaturesXhr = function(url, format, success) { if (!source) { source = ol.xml.parse(xhrIo.getResponseText()); } + } else if (type == ol.format.FormatType.ARRAY_BUFFER) { + source = xhrIo.getResponse(); } else { goog.asserts.fail('unexpected format type'); } diff --git a/src/ol/format/featureformat.js b/src/ol/format/featureformat.js index 59d0c77943..25c10aa79d 100644 --- a/src/ol/format/featureformat.js +++ b/src/ol/format/featureformat.js @@ -95,7 +95,7 @@ ol.format.Feature.prototype.readFeature = goog.abstractMethod; /** * Read all features from a source. * - * @param {Document|Node|Object|string} source Source. + * @param {Document|Node|ArrayBuffer|Object|string} source Source. * @param {olx.format.ReadOptions=} opt_options Read options. * @return {Array.} Features. */ diff --git a/src/ol/format/format.js b/src/ol/format/format.js index e0cca0fdae..3fa3586e3f 100644 --- a/src/ol/format/format.js +++ b/src/ol/format/format.js @@ -5,6 +5,7 @@ goog.provide('ol.format.FormatType'); * @enum {string} */ ol.format.FormatType = { + ARRAY_BUFFER: 'arraybuffer', JSON: 'json', TEXT: 'text', XML: 'xml' diff --git a/src/ol/format/mvtformat.js b/src/ol/format/mvtformat.js new file mode 100644 index 0000000000..97936f1585 --- /dev/null +++ b/src/ol/format/mvtformat.js @@ -0,0 +1,196 @@ +//FIXME Implement projection handling + +goog.provide('ol.format.MVT'); + +goog.require('goog.array'); +goog.require('goog.asserts'); +goog.require('ol.Feature'); +goog.require('ol.ext.pbf'); +goog.require('ol.ext.vectortile'); +goog.require('ol.format.Feature'); +goog.require('ol.format.FormatType'); +goog.require('ol.geom.Geometry'); +goog.require('ol.geom.GeometryLayout'); +goog.require('ol.geom.LineString'); +goog.require('ol.geom.MultiLineString'); +goog.require('ol.geom.MultiPoint'); +goog.require('ol.geom.Point'); +goog.require('ol.geom.Polygon'); +goog.require('ol.proj'); +goog.require('ol.proj.Projection'); +goog.require('ol.proj.Units'); + + + +/** + * @classdesc + * Feature format for reading data in the Mapbox MVT format. + * + * @constructor + * @extends {ol.format.Feature} + * @param {olx.format.MVTOptions=} opt_options Options. + * @api + */ +ol.format.MVT = function(opt_options) { + + goog.base(this); + + var options = goog.isDef(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 {string} + */ + this.geometryName_ = goog.isDef(options.geometryName) ? + options.geometryName : 'geometry'; + + /** + * @private + * @type {string} + */ + this.layerName_ = goog.isDef(options.layerName) ? options.layerName : 'layer'; + + /** + * @private + * @type {Array.} + */ + this.layers_ = goog.isDef(options.layers) ? options.layers : null; + +}; +goog.inherits(ol.format.MVT, ol.format.Feature); + + +/** + * @inheritDoc + */ +ol.format.MVT.prototype.getType = function() { + return ol.format.FormatType.ARRAY_BUFFER; +}; + + +/** + * @private + * @param {Object} rawFeature Raw Mapbox feature. + * @param {olx.format.ReadOptions=} opt_options Read options. + * @return {ol.Feature} Feature. + */ +ol.format.MVT.prototype.readFeature_ = function(rawFeature, opt_options) { + var feature = new ol.Feature(); + var values = rawFeature.properties; + var geometry = ol.format.Feature.transformWithOptions( + ol.format.MVT.readGeometry_(rawFeature), false, + this.adaptOptions(opt_options)); + if (!goog.isNull(geometry)) { + goog.asserts.assertInstanceof(geometry, ol.geom.Geometry); + values[this.geometryName_] = geometry; + } + feature.setProperties(rawFeature.properties); + feature.setGeometryName(this.geometryName_); + return feature; +}; + + +/** + * @inheritDoc + */ +ol.format.MVT.prototype.readFeatures = function(source, opt_options) { + goog.asserts.assertInstanceof(source, ArrayBuffer); + + var layerName = this.layerName_; + var layers = this.layers_; + + var pbf = new ol.ext.pbf(source); + var tile = new ol.ext.vectortile.VectorTile(pbf); + var features = []; + var layer, feature; + for (var name in tile.layers) { + if (!goog.isNull(layers) && !goog.array.contains(layers, name)) { + continue; + } + layer = tile.layers[name]; + + for (var i = 0, ii = layer.length; i < layer.length; ++i) { + feature = this.readFeature_(layer.feature(i), opt_options); + feature.set(layerName, name); + features.push(feature); + } + } + + return features; +}; + + +/** + * @inheritDoc + */ +ol.format.MVT.prototype.readProjection = function(source) { + return this.defaultDataProjection; +}; + + +/** + * Sets the layers that features will be read from. + * @param {Array.} layers Layers. + * @api + */ +ol.format.MVT.prototype.setLayers = function(layers) { + this.layers_ = layers; +}; + + +/** + * @private + * @param {Object} rawFeature Raw Mapbox feature. + * @return {ol.geom.Geometry} Geometry. + */ +ol.format.MVT.readGeometry_ = function(rawFeature) { + var type = rawFeature.type; + if (type === 0) { + return null; + } + + var coords = rawFeature.loadGeometry(); + + var end = 0; + var ends = []; + var flatCoordinates = []; + var line, coord; + for (var i = 0, ii = coords.length; i < ii; ++i) { + line = coords[i]; + for (var j = 0, jj = line.length; j < jj; ++j) { + coord = line[j]; + // Non-tilespace coords can be calculated here when a TileGrid and + // TileCoord are known. + flatCoordinates.push(coord.x, coord.y); + } + end += 2 * j; + ends.push(end); + } + + var geom; + if (type === 1) { + geom = coords.length === 1 ? + new ol.geom.Point(null) : new ol.geom.MultiPoint(null); + } else if (type === 2) { + if (coords.length === 1) { + geom = new ol.geom.LineString(null); + } else { + geom = new ol.geom.MultiLineString(null); + } + } else { + geom = new ol.geom.Polygon(null); + } + + geom.setFlatCoordinates(ol.geom.GeometryLayout.XY, flatCoordinates, + ends); + + return geom; +}; diff --git a/test/spec/ol/data/14-8938-5680.vector.pbf b/test/spec/ol/data/14-8938-5680.vector.pbf new file mode 100644 index 0000000000000000000000000000000000000000..0ed0c1ee240ac78a8ae5f6921253d8a8325c47ef GIT binary patch literal 46937 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