re-add tests

This commit is contained in:
Mike Morris 2014-04-16 17:36:42 -04:00
parent 03d5087b06
commit 360df418bf
11 changed files with 2545 additions and 0 deletions

View File

@ -0,0 +1,341 @@
{
"layers": {
"landuse": {
"version": 1,
"name": "landuse",
"extent": 4096,
"length": 3,
"shaping": {},
"faces": [],
"_keys": [
"class",
"osm_id"
],
"_values": [
"park",
0,
0,
"sand",
0
],
"_features": [
13,
225,
325
]
},
"waterway": {
"version": 1,
"name": "waterway",
"extent": 4096,
"length": 11,
"shaping": {},
"faces": [],
"_keys": [
"osm_id",
"type"
],
"_values": [
102639147,
"stream",
28483936,
28544165,
28544279,
28544488,
28544489,
28544658,
28544491,
28544660,
28544661,
28544659
],
"_features": [
556,
629,
925,
973,
1049,
1146,
1193,
1234,
1272,
1298,
1357
]
},
"water": {
"version": 1,
"name": "water",
"extent": 4096,
"length": 5,
"shaping": {},
"faces": [],
"_keys": [
"osm_id"
],
"_values": [
0,
0,
0,
0,
0
],
"_features": [
1555,
2026,
2107,
2153,
2201
]
},
"road": {
"version": 1,
"name": "road",
"extent": 4096,
"length": 37,
"shaping": {},
"faces": [],
"_keys": [
"class",
"oneway",
"osm_id",
"type"
],
"_values": [
"street_limited",
0,
12176014,
"residential",
"street",
102638413,
12190176,
125871922,
"unclassified",
12172969,
12171395,
12172974,
12171388,
12176906,
12184872,
12188141,
82660225,
12185663,
232292986,
236784059,
12187833,
12180093,
12181692,
12179250,
12182785,
207142176,
232292987,
12181251,
112429240,
12172937,
12178793,
12184634,
12175654,
12187257,
12183699,
"main",
112926169,
"primary",
239213058,
174215004,
157338248,
174215024,
88159974,
"tertiary",
12177297,
12177319
],
"_features": [
2402,
2524,
2619,
2653,
2767,
2836,
2870,
2903,
2981,
3009,
3042,
3070,
3107,
3144,
3214,
3245,
3367,
3427,
3470,
3501,
3546,
3615,
3660,
3689,
3719,
3772,
3822,
3857,
3889,
3923,
4101,
4159,
4281,
4570,
4611,
4919,
4958
]
},
"bridge": {
"version": 1,
"name": "bridge",
"extent": 4096,
"length": 2,
"shaping": {},
"faces": [],
"_keys": [
"class",
"oneway",
"osm_id",
"type"
],
"_values": [
"service",
0,
207142221,
"track",
"street",
207142175,
"residential"
],
"_features": [
5723,
5752
]
},
"place_label": {
"version": 1,
"name": "place_label",
"extent": 4096,
"length": 3,
"shaping": {},
"faces": [],
"_keys": [
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"type",
"ldir",
"scalerank"
],
"_values": [
"Mill Valley",
0,
"town",
"",
"Tamalpais Valley",
0,
0,
"hamlet",
"Muir Beach",
0
],
"_features": [
6058,
6096,
6138
]
},
"poi_label": {
"version": 1,
"name": "poi_label",
"extent": 4096,
"length": 1,
"shaping": {},
"faces": [],
"_keys": [
"localrank",
"maki",
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"ref",
"scalerank",
"type"
],
"_values": [
1,
"park",
"Muir Woods National Monument",
0,
"",
"Park"
],
"_features": [
6406
]
},
"road_label": {
"version": 1,
"name": "road_label",
"extent": 4096,
"length": 7,
"shaping": {},
"faces": [],
"_keys": [
"class",
"len",
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"ref",
"reflen"
],
"_values": [
"main",
7396.168723572097,
"Panoramic Hwy",
"Panoramic Highway",
88159974,
"",
0,
4357.193150547803,
"Shoreline Hwy",
"Shoreline Highway",
157338250,
3528.44005555027,
174215024,
2928.2679350617123,
125871918,
7600.032638046431,
12177319,
2513.4221036393283,
174215004,
1716.9016582189813,
12188378
],
"_features": [
6622,
6783,
6879,
7328,
7512,
8269,
8570
]
}
},
"faces": {}
}

1137
test/expected/shape.json Normal file

File diff suppressed because it is too large Load Diff

337
test/expected/simplify.json Normal file
View File

@ -0,0 +1,337 @@
{
"layers": {
"landuse": {
"version": 2,
"name": "landuse",
"extent": 4096,
"length": 3,
"shaping": {},
"faces": [],
"_keys": [
"class",
"osm_id"
],
"_values": [
"park",
0,
0,
"sand",
0
],
"_features": [
13,
223,
314
]
},
"waterway": {
"version": 2,
"name": "waterway",
"extent": 4096,
"length": 11,
"shaping": {},
"faces": [],
"_keys": [
"osm_id",
"type"
],
"_values": [
102639147,
"stream",
28483936,
28544165,
28544279,
28544488,
28544489,
28544658,
28544491,
28544660,
28544661,
28544659
],
"_features": [
543,
616,
912,
960,
1036,
1133,
1180,
1221,
1259,
1285,
1344
]
},
"water": {
"version": 2,
"name": "water",
"extent": 4096,
"length": 1,
"shaping": {},
"faces": [],
"_keys": [
"osm_id"
],
"_values": [
0,
0,
0,
0,
0
],
"_features": [
1542
]
},
"road": {
"version": 2,
"name": "road",
"extent": 4096,
"length": 37,
"shaping": {},
"faces": [],
"_keys": [
"class",
"oneway",
"osm_id",
"type"
],
"_values": [
"street_limited",
0,
12176014,
"residential",
"street",
102638413,
12190176,
125871922,
"unclassified",
12172969,
12171395,
12172974,
12171388,
12176906,
12184872,
12188141,
82660225,
12185663,
232292986,
236784059,
12187833,
12180093,
12181692,
12179250,
12182785,
207142176,
232292987,
12181251,
112429240,
12172937,
12178793,
12184634,
12175654,
12187257,
12183699,
"main",
112926169,
"primary",
239213058,
174215004,
157338248,
174215024,
88159974,
"tertiary",
12177297,
12177319
],
"_features": [
2190,
2312,
2407,
2441,
2555,
2624,
2658,
2691,
2769,
2797,
2830,
2858,
2895,
2932,
3002,
3033,
3155,
3215,
3258,
3289,
3334,
3403,
3448,
3477,
3507,
3560,
3610,
3645,
3677,
3711,
3889,
3947,
4069,
4358,
4399,
4707,
4746
]
},
"bridge": {
"version": 2,
"name": "bridge",
"extent": 4096,
"length": 2,
"shaping": {},
"faces": [],
"_keys": [
"class",
"oneway",
"osm_id",
"type"
],
"_values": [
"service",
0,
207142221,
"track",
"street",
207142175,
"residential"
],
"_features": [
5511,
5540
]
},
"place_label": {
"version": 2,
"name": "place_label",
"extent": 4096,
"length": 3,
"shaping": {},
"faces": [],
"_keys": [
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"type",
"ldir",
"scalerank"
],
"_values": [
"Mill Valley",
0,
"town",
"",
"Tamalpais Valley",
0,
0,
"hamlet",
"Muir Beach",
0
],
"_features": [
5682,
5720,
5762
]
},
"poi_label": {
"version": 2,
"name": "poi_label",
"extent": 4096,
"length": 1,
"shaping": {},
"faces": [],
"_keys": [
"localrank",
"maki",
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"ref",
"scalerank",
"type"
],
"_values": [
1,
"park",
"Muir Woods National Monument",
0,
"",
"Park"
],
"_features": [
6010
]
},
"road_label": {
"version": 2,
"name": "road_label",
"extent": 4096,
"length": 7,
"shaping": {},
"faces": [],
"_keys": [
"class",
"len",
"name",
"name_de",
"name_en",
"name_es",
"name_fr",
"osm_id",
"ref",
"reflen"
],
"_values": [
"main",
7396.168723572097,
"Panoramic Hwy",
"Panoramic Highway",
88159974,
"",
0,
4357.193150547803,
"Shoreline Hwy",
"Shoreline Highway",
157338250,
3528.44005555027,
174215024,
2928.2679350617123,
125871918,
7600.032638046431,
12177319,
2513.4221036393283,
174215004,
1716.9016582189813,
12188378
],
"_features": [
6226,
6387,
6483,
6932,
7116,
7873,
8174
]
}
},
"faces": {}
}

Binary file not shown.

118
test/format/ieee754.js Normal file
View File

@ -0,0 +1,118 @@
'use strict';
// Copyright (c) 2008, Fair Oaks Labs, Inc.
// All rights reserved.
//
// Redistribution and use in source and binary forms, with or without
// modification, are permitted provided that the following conditions are met:
//
// * Redistributions of source code must retain the above copyright notice,
// this list of conditions and the following disclaimer.
//
// * Redistributions in binary form must reproduce the above copyright notice,
// this list of conditions and the following disclaimer in the documentation
// and/or other materials provided with the distribution.
//
// * Neither the name of Fair Oaks Labs, Inc. nor the names of its contributors
// may be used to endorse or promote products derived from this software
// without specific prior written permission.
//
// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS"
// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE
// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
// POSSIBILITY OF SUCH DAMAGE.
//
//
// Modifications to writeIEEE754 to support negative zeroes made by Brian White
exports.readIEEE754 = function(buffer, offset, isBE, mLen, nBytes) {
var e, m,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
nBits = -7,
i = isBE ? 0 : (nBytes - 1),
d = isBE ? 1 : -1,
s = buffer[offset + i];
i += d;
e = s & ((1 << (-nBits)) - 1);
s >>= (-nBits);
nBits += eLen;
for (; nBits > 0; e = e * 256 + buffer[offset + i], i += d, nBits -= 8);
m = e & ((1 << (-nBits)) - 1);
e >>= (-nBits);
nBits += mLen;
for (; nBits > 0; m = m * 256 + buffer[offset + i], i += d, nBits -= 8);
if (e === 0) {
e = 1 - eBias;
} else if (e === eMax) {
return m ? NaN : ((s ? -1 : 1) * Infinity);
} else {
m = m + Math.pow(2, mLen);
e = e - eBias;
}
return (s ? -1 : 1) * m * Math.pow(2, e - mLen);
};
exports.writeIEEE754 = function(buffer, value, offset, isBE, mLen, nBytes) {
var e, m, c,
eLen = nBytes * 8 - mLen - 1,
eMax = (1 << eLen) - 1,
eBias = eMax >> 1,
rt = (mLen === 23 ? Math.pow(2, -24) - Math.pow(2, -77) : 0),
i = isBE ? (nBytes - 1) : 0,
d = isBE ? -1 : 1,
s = value < 0 || (value === 0 && 1 / value < 0) ? 1 : 0;
value = Math.abs(value);
if (isNaN(value) || value === Infinity) {
m = isNaN(value) ? 1 : 0;
e = eMax;
} else {
e = Math.floor(Math.log(value) / Math.LN2);
if (value * (c = Math.pow(2, -e)) < 1) {
e--;
c *= 2;
}
if (e + eBias >= 1) {
value += rt / c;
} else {
value += rt * Math.pow(2, 1 - eBias);
}
if (value * c >= 2) {
e++;
c /= 2;
}
if (e + eBias >= eMax) {
m = 0;
e = eMax;
} else if (e + eBias >= 1) {
m = (value * c - 1) * Math.pow(2, mLen);
e = e + eBias;
} else {
m = value * Math.pow(2, eBias - 1) * Math.pow(2, mLen);
e = 0;
}
}
for (; mLen >= 8; buffer[offset + i] = m & 0xff, i += d, m /= 256, mLen -= 8);
e = (e << mLen) | m;
eLen += mLen;
for (; eLen > 0; buffer[offset + i] = e & 0xff, i += d, e /= 256, eLen -= 8);
buffer[offset + i - d] |= s * 128;
};

116
test/format/protobuf.js Normal file
View File

@ -0,0 +1,116 @@
'use strict';
var ieee754 = require('./ieee754.js');
module.exports = Protobuf;
function Protobuf(buf) {
this.buf = buf;
this.length = buf.length;
this.pos = 0;
}
Protobuf.prototype.destroy = function() {
this.buf = null;
};
Protobuf.prototype.readUInt32 = function() {
var val = this.readUInt32LE(this.pos);
this.pos += 4;
return val;
};
Protobuf.prototype.readUInt64 = function() {
var val = this.readUInt64LE(this.pos);
this.pos += 8;
return val;
};
Protobuf.prototype.readDouble = function() {
var val = ieee754.readIEEE754(this.buf, this.pos, false, 52, 8);
this.pos += 8;
return val;
};
Protobuf.prototype.readVarint = function() {
// TODO: bounds checking
var pos = this.pos;
if (this.buf[pos] <= 0x7f) {
this.pos++;
return this.buf[pos];
} else if (this.buf[pos + 1] <= 0x7f) {
this.pos += 2;
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] << 7);
} else if (this.buf[pos + 2] <= 0x7f) {
this.pos += 3;
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2]) << 14;
} else if (this.buf[pos + 3] <= 0x7f) {
this.pos += 4;
return (this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21;
} else if (this.buf[pos + 4] <= 0x7f) {
this.pos += 5;
return ((this.buf[pos] & 0x7f) | (this.buf[pos + 1] & 0x7f) << 7 | (this.buf[pos + 2] & 0x7f) << 14 | (this.buf[pos + 3]) << 21) + (this.buf[pos + 4] * 268435456);
} else {
this.skip(0);
return 0;
// throw new Error("TODO: Handle 6+ byte varints");
}
};
Protobuf.prototype.readSVarint = function() {
var num = this.readVarint();
if (num > 2147483647) throw new Error('TODO: Handle numbers >= 2^30');
// zigzag encoding
return ((num >> 1) ^ -(num & 1));
};
Protobuf.prototype.readString = function() {
var bytes = this.readVarint();
// TODO: bounds checking
var chr = String.fromCharCode;
var b = this.buf;
var p = this.pos;
var end = this.pos + bytes;
var str = '';
while (p < end) {
if (b[p] <= 0x7F) str += chr(b[p++]);
else if (b[p] <= 0xBF) throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
else if (b[p] <= 0xDF) str += chr((b[p++] & 0x1F) << 6 | (b[p++] & 0x3F));
else if (b[p] <= 0xEF) str += chr((b[p++] & 0x1F) << 12 | (b[p++] & 0x3F) << 6 | (b[p++] & 0x3F));
else if (b[p] <= 0xF7) p += 4; // We can't handle these codepoints in JS, so skip.
else if (b[p] <= 0xFB) p += 5;
else if (b[p] <= 0xFD) p += 6;
else throw new Error('Invalid UTF-8 codepoint: ' + b[p]);
}
this.pos += bytes;
return str;
};
Protobuf.prototype.readBuffer = function() {
var bytes = this.readVarint();
var buffer = this.buf.subarray(this.pos, this.pos + bytes);
this.pos += bytes;
return buffer;
};
Protobuf.prototype.readPacked = function(type) {
// TODO: bounds checking
var bytes = this.readVarint();
var end = this.pos + bytes;
var array = [];
while (this.pos < end) {
array.push(this['read' + type]());
}
return array;
};
Protobuf.prototype.skip = function(val) {
// TODO: bounds checking
var type = val & 0x7;
switch (type) {
/* varint */ case 0: while (this.buf[this.pos++] > 0x7f); break;
/* 64 bit */ case 1: this.pos += 8; break;
/* length */ case 2: var bytes = this.readVarint(); this.pos += bytes; break;
/* 32 bit */ case 5: this.pos += 4; break;
default: throw new Error('Unimplemented type: ' + type);
}
};

102
test/format/vectortile.js Normal file
View File

@ -0,0 +1,102 @@
'use strict';
var VectorTileLayer = require('./vectortilelayer');
module.exports = VectorTile;
function VectorTile(buffer, end) {
// Public
this.layers = {};
this.faces = {};
// Private
this._buffer = buffer;
var val, tag;
if (typeof end === 'undefined') end = buffer.length;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 3) {
var layer = this.readLayer();
if (layer.length) {
this.layers[layer.name] = layer;
}
} else if (tag == 4) {
var face = this.readFace();
this.faces[face.family + ' ' + face.style] = face;
} else {
// console.warn('skipping tile tag ' + tag);
buffer.skip(val);
}
}
}
VectorTile.prototype.readLayer = function() {
var buffer = this._buffer;
var bytes = buffer.readVarint();
var end = buffer.pos + bytes;
var layer = new VectorTileLayer(buffer, end);
buffer.pos = end;
return layer;
};
VectorTile.prototype.readFace = function() {
var buffer = this._buffer;
var face = { glyphs: {} };
var bytes = buffer.readVarint();
var val, tag;
var end = buffer.pos + bytes;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 1) {
face.family = buffer.readString();
} else if (tag == 2) {
face.style = buffer.readString();
} else if (tag == 5) {
var glyph = this.readGlyph();
face.glyphs[glyph.id] = glyph;
} else {
buffer.skip(val);
}
}
return face;
};
VectorTile.prototype.readGlyph = function() {
var buffer = this._buffer;
var glyph = {};
var bytes = buffer.readVarint();
var val, tag;
var end = buffer.pos + bytes;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 1) {
glyph.id = buffer.readVarint();
} else if (tag == 2) {
glyph.bitmap = buffer.readBuffer();
} else if (tag == 3) {
glyph.width = buffer.readVarint();
} else if (tag == 4) {
glyph.height = buffer.readVarint();
} else if (tag == 5) {
glyph.left = buffer.readSVarint();
} else if (tag == 6) {
glyph.top = buffer.readSVarint();
} else if (tag == 7) {
glyph.advance = buffer.readVarint();
} else {
buffer.skip(val);
}
}
return glyph;
};

View File

@ -0,0 +1,145 @@
'use strict';
var VectorTilePoint = require('./vectortilepoint.js');
/*
* Construct a new vector tile feature given a buffer.
*
* @param {object} buffer
* @param {number} [end]
* @param {extent}
* @param {object} keys
* @param {object} values
*/
module.exports = VectorTileFeature;
function VectorTileFeature(buffer, end, extent, keys, values) {
// Public
this._extent = extent;
this._type = 0;
// Private
this._buffer = buffer;
this._geometry = -1;
if (typeof end === 'undefined') {
end = buffer.length;
}
var val, tag;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 1) {
this._id = buffer.readVarint();
} else if (tag == 2) {
var tag_end = buffer.pos + buffer.readVarint();
while (buffer.pos < tag_end) {
var key = keys[buffer.readVarint()];
var value = values[buffer.readVarint()];
this[key] = value;
}
} else if (tag == 3) {
this._type = buffer.readVarint();
} else if (tag == 4) {
this._geometry = buffer.pos;
buffer.skip(val);
} else {
buffer.skip(val);
}
}
}
VectorTileFeature.Unknown = 0;
VectorTileFeature.Point = 1;
VectorTileFeature.LineString = 2;
VectorTileFeature.Polygon = 3;
VectorTileFeature.mapping = [];
VectorTileFeature.mapping[VectorTileFeature.Point] = 'point';
VectorTileFeature.mapping[VectorTileFeature.LineString] = 'line';
VectorTileFeature.mapping[VectorTileFeature.Polygon] = 'fill';
VectorTileFeature.prototype.loadGeometry = function() {
var buffer = this._buffer;
buffer.pos = this._geometry;
var bytes = buffer.readVarint();
var end = buffer.pos + bytes;
var cmd = 1, length = 0, x = 0, y = 0;
var lines = [];
var line = null;
while (buffer.pos < end) {
if (!length) {
var cmd_length = buffer.readVarint();
cmd = cmd_length & 0x7;
length = cmd_length >> 3;
}
length--;
if (cmd == 1 || cmd == 2) {
x += buffer.readSVarint();
y += buffer.readSVarint();
if (cmd == 1) {
// moveTo
if (line) {
lines.push(line);
}
line = [];
}
line.push(new VectorTilePoint(x, y));
} else if (cmd == 7) {
// closePolygon
line.push(line[0]);
} else {
throw new Error('unknown command ' + cmd);
}
}
if (line) {
lines.push(line);
}
return lines;
};
VectorTileFeature.prototype.bbox = function() {
var buffer = this._buffer;
buffer.pos = this._geometry;
var bytes = buffer.readVarint();
var end = buffer.pos + bytes;
var cmd = 1, length = 0, x = 0, y = 0;
var x1 = Infinity, x2 = -Infinity, y1 = Infinity, y2 = -Infinity;
while (buffer.pos < end) {
if (!length) {
var cmd_length = buffer.readVarint();
cmd = cmd_length & 0x7;
length = cmd_length >> 3;
}
length--;
if (cmd == 1 || cmd == 2) {
x += buffer.readSVarint();
y += buffer.readSVarint();
if (x < x1) x1 = x;
if (x > x2) x2 = x;
if (y < y1) y1 = y;
if (y > y2) y2 = y;
} else if (cmd != 7) {
throw new Error('unknown command ' + cmd);
}
}
return { x1: x1, y1: y1, x2: x2, y2: y2 };
};

View File

@ -0,0 +1,150 @@
'use strict';
var VectorTileFeature = require('./vectortilefeature.js');
module.exports = VectorTileLayer;
function VectorTileLayer(buffer, end) {
// Public
this.version = 1;
this.name = null;
this.extent = 4096;
this.length = 0;
this.shaping = {};
this.faces = [];
// Private
this._buffer = buffer;
this._keys = [];
this._values = [];
this._features = [];
var stack_index = [];
var labels = [];
var val, tag;
if (typeof end === 'undefined') end = buffer.length;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 15) {
this.version = buffer.readVarint();
} else if (tag == 1) {
this.name = buffer.readString();
} else if (tag == 5) {
this.extent = buffer.readVarint();
} else if (tag == 2) {
this.length++;
this._features.push(buffer.pos);
buffer.skip(val);
} else if (tag == 3) {
this._keys.push(buffer.readString());
} else if (tag == 4) {
this._values.push(this.readFeatureValue());
} else if (tag == 7) {
this.faces.push(buffer.readString());
} else if (tag == 8) {
labels.push(this.readLabel());
} else if (tag == 9) {
stack_index.push(buffer.readString());
} else {
console.warn('skipping layer tag ' + tag);
buffer.skip(val);
}
}
// Build index of [stack][text] => shaping information
var shaping = this.shaping;
for (var i = 0; i < labels.length; i++) {
var label = labels[i];
var text = this._values[label.text];
var stack = stack_index[label.stack];
if (!(stack in shaping)) shaping[stack] = {};
shaping[stack][text] = label.glyphs;
}
}
VectorTileLayer.prototype.readFeatureValue = function() {
var buffer = this._buffer;
var value = null;
var bytes = buffer.readVarint();
var val, tag;
var end = buffer.pos + bytes;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 1) {
value = buffer.readString();
} else if (tag == 2) {
throw new Error('read float');
} else if (tag == 3) {
value = buffer.readDouble();
} else if (tag == 4) {
value = buffer.readVarint();
} else if (tag == 5) {
throw new Error('read uint');
} else if (tag == 6) {
value = buffer.readSVarint();
} else if (tag == 7) {
value = Boolean(buffer.readVarint());
} else {
buffer.skip(val);
}
}
return value;
};
VectorTileLayer.prototype.readLabel = function() {
var label = { glyphs: [] };
var faces, glyphs, x, y;
var buffer = this._buffer;
var bytes = buffer.readVarint();
var val, tag;
var end = buffer.pos + bytes;
while (buffer.pos < end) {
val = buffer.readVarint();
tag = val >> 3;
if (tag == 1) {
label.text = buffer.readVarint();
} else if (tag == 2) {
label.stack = buffer.readVarint();
} else if (tag == 3) {
faces = buffer.readPacked('Varint');
} else if (tag == 4) {
glyphs = buffer.readPacked('Varint');
} else if (tag == 5) {
x = buffer.readPacked('Varint');
} else if (tag == 6) {
y = buffer.readPacked('Varint');
} else {
buffer.skip(val);
}
}
for (var i = 0; i < glyphs.length; i++) {
label.glyphs.push({ face: faces[i], glyph: glyphs[i], x: x[i], y: y[i] });
}
return label;
};
/*
* Return feature `i` from this layer as a `VectorTileFeature`
*
* @param {number} i
* @returns {VectorTileFeature}
*/
VectorTileLayer.prototype.feature = function(i) {
if (i < 0 || i >= this._features.length) {
throw new Error('feature index out of bounds');
}
this._buffer.pos = this._features[i];
var end = this._buffer.readVarint() + this._buffer.pos;
return new VectorTileFeature(this._buffer, end, this.extent, this._keys, this._values);
};

View File

@ -0,0 +1,11 @@
'use strict';
module.exports = VectorTilePoint;
function VectorTilePoint(x, y) {
this.x = x;
this.y = y;
}
VectorTilePoint.prototype.toString = function() {
return "Point(" + this.x + ", " + this.y + ")";
};

88
test/test.js Normal file
View File

@ -0,0 +1,88 @@
var fontserver = require('../index.js');
var assert = require('assert');
var zlib = require('zlib');
var fs = require('fs');
var zdata = fs.readFileSync(__dirname + '/fixtures/mapbox-streets-v4.13.1306.3163.vector.pbf');
var Protobuf = require('./format/protobuf');
var VectorTile = require('./format/vectortile');
function nobuffer(key, val) {
return key !== '_buffer' && key !== 'bitmap' ? val : undefined;
}
function jsonEqual(key, json) {
fs.writeFileSync(__dirname + '/expected/'+key+'.json', JSON.stringify(json, null, 2));
assert.deepEqual(json, require('./expected/'+key+'.json'));
}
describe('convert', function() {
var data;
before(function(done) {
zlib.inflate(zdata, function(err, d) {
assert.ifError(err);
data = d;
done();
});
});
it('serialize', function(done) {
var tile = new fontserver.Tile(data);
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
var json = JSON.parse(JSON.stringify(vt, nobuffer));
jsonEqual('serialize', json);
done();
});
it('simplify', function(done) {
var tile = new fontserver.Tile(data);
tile.simplify(function(err) {
assert.ifError(err);
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
var json = JSON.parse(JSON.stringify(vt, nobuffer));
jsonEqual('simplify', json);
done();
});
});
it('simplify (x10)', function(done) {
this.timeout(10000);
var remaining = 10;
for (var i = 0; i < 10; i++) (function() {
var tile = new fontserver.Tile(data);
tile.simplify(function(err) {
assert.ifError(err);
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
var json = JSON.parse(JSON.stringify(vt, nobuffer));
jsonEqual('simplify', json);
if (!--remaining) return done();
});
})();
});
it('shape', function(done) {
var tile = new fontserver.Tile(data);
tile.shape('Open Sans', function(err) {
assert.ifError(err);
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
var json = JSON.parse(JSON.stringify(vt, nobuffer));
jsonEqual('shape', json);
done();
});
});
it('shape (x10)', function(done) {
this.timeout(10000);
var remaining = 10;
for (var i = 0; i < 10; i++) (function() {
var tile = new fontserver.Tile(data);
tile.shape('Open Sans', function(err) {
assert.ifError(err);
var vt = new VectorTile(new Protobuf(new Uint8Array(tile.serialize())));
var json = JSON.parse(JSON.stringify(vt, nobuffer));
jsonEqual('shape', json);
if (!--remaining) return done();
});
})();
});
});