From b15016a0e45618087ec889c657dd2407541c2534 Mon Sep 17 00:00:00 2001 From: John Firebaugh Date: Fri, 20 Feb 2015 21:07:06 -0800 Subject: [PATCH] Add feature.toGeoJSON(x, y, z) --- lib/vectortilefeature.js | 33 +++++++++++++++++++++++ package.json | 3 ++- test/parse.test.js | 58 ++++++++++++++++++++++++++++++++++++++++ 3 files changed, 93 insertions(+), 1 deletion(-) diff --git a/lib/vectortilefeature.js b/lib/vectortilefeature.js index 667d5dd..4f30479 100644 --- a/lib/vectortilefeature.js +++ b/lib/vectortilefeature.js @@ -125,3 +125,36 @@ VectorTileFeature.prototype.bbox = function() { return [x1, y1, x2, y2]; }; + +var SphericalMercator = require('sphericalmercator'); + +VectorTileFeature.prototype.toGeoJSON = function(x, y, z) { + var merc = new SphericalMercator({size: this.extent}), + x0 = this.extent * x, + y0 = this.extent * y, + coords = this.loadGeometry(), + type = VectorTileFeature.types[this.type]; + + for (var i = 0; i < coords.length; i++) { + var line = coords[i]; + for (var j = 0; j < line.length; j++) { + var p = line[j]; + line[j] = merc.ll([p.x + x0, p.y + y0], z); + } + } + + if (type === 'Point') { + coords = coords[0][0]; + } else if (type === 'LineString') { + coords = coords[0]; + } + + return { + type: "Feature", + geometry: { + type: type, + coordinates: coords + }, + properties: this.properties + }; +}; diff --git a/package.json b/package.json index 45764ec..161fed5 100644 --- a/package.json +++ b/package.json @@ -6,7 +6,8 @@ "license": "BSD", "main": "index.js", "dependencies": { - "point-geometry": "0.0.0" + "point-geometry": "0.0.0", + "sphericalmercator": "^1.0.3" }, "devDependencies": { "benchmark": "^1.0.0", diff --git a/test/parse.test.js b/test/parse.test.js index 3679604..2bc0ba5 100644 --- a/test/parse.test.js +++ b/test/parse.test.js @@ -55,6 +55,64 @@ test('parsing vector tiles', function(t) { t.deepEqual(building, [ [ { x: 1, y: 2 }, { x: 3, y: 4 }, { x: 2032, y: -31 }, { x: 2032, y: -32 }, { x: 2039, y: -32 } ] ]); t.end(); }); + + t.test('toGeoJSON', function(t) { + var tile = new VectorTile(new Protobuf(data)); + + function close(actual, expected) { + t.equal(actual.length, expected.length); + for (var i = 0; i < actual.length; i++) { + if (actual[i].length) { + close(actual[i], expected[i]); + } else { + t.ok(Math.abs(actual[i] - expected[i]) < 1e-6); + } + } + } + + var point = tile.layers.poi_label.feature(11).toGeoJSON(8801, 5371, 14); + t.deepEqual(point.type, 'Feature'); + t.deepEqual(point.properties, { + localrank: 1, + maki: 'park', + name: 'Mauerpark', + name_de: 'Mauerpark', + name_en: 'Mauerpark', + name_es: 'Mauerpark', + name_fr: 'Mauerpark', + osm_id: 3000003150561, + ref: '', + scalerank: 2, + type: 'Park' + }); + t.deepEqual(point.geometry.type, 'Point'); + close(point.geometry.coordinates, [13.402258157730103, 52.54398925380624]); + + var line = tile.layers.bridge.feature(0).toGeoJSON(8801, 5371, 14); + t.deepEqual(line.type, 'Feature'); + t.deepEqual(line.properties, { + class: 'service', + oneway: 0, + osm_id: 238162948, + type: 'service' + }); + t.deepEqual(line.geometry.type, 'LineString'); + close(line.geometry.coordinates, + [[13.399457931518555, 52.546334844036416], [13.399441838264465, 52.546504478525016]]); + + var poly = tile.layers.building.feature(0).toGeoJSON(8801, 5371, 14); + t.deepEqual(poly.type, 'Feature'); + t.deepEqual(poly.properties, { + osm_id: 1000267229912 + }); + t.deepEqual(poly.geometry.type, 'Polygon'); + close(poly.geometry.coordinates, + [[[13.392285704612732, 52.54974045706258], [13.392264246940613, 52.549737195107554], + [13.392248153686523, 52.549737195107554], [13.392248153686523, 52.54974045706258], + [13.392285704612732, 52.54974045706258]]]); + + t.end(); + }) }); test('VectorTileLayer', function(t) {