This repository has been archived by the owner on Apr 2, 2019. It is now read-only.
-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathoverzoomer.js
90 lines (75 loc) · 2.83 KB
/
overzoomer.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
'use strict';
/*
OverZoomer is a storage wrapper. Given a tile source, it will retrieve requested tile from it,
or if missing, will zoom out until it finds a tile, and extract needed portion of it.
*/
const Promise = require('bluebird');
const zlib = Promise.promisifyAll(require('zlib'));
const Err = require('@kartotherian/err');
const checkType = require('@kartotherian/input-validator');
const uptile = require('tilelive-promise');
let core;
function OverZoomer(uri, callback) {
let self = this;
return Promise.try(() => {
self = uptile(self);
let params = checkType.normalizeUrl(uri).query;
if (!params.source) {
throw new Err("Uri must include 'source' query parameter: %j", uri);
}
self.minzoom = typeof params.minzoom === 'undefined' ? 0 : parseInt(params.minzoom);
self.maxzoom = typeof params.maxzoom === 'undefined' ? 22 : parseInt(params.maxzoom);
return core.loadSource(params.source);
}).then(source => {
self.source = uptile(source);
return self;
}).nodeify(callback);
}
OverZoomer.prototype.getAsync = Promise.method(function(opts) {
const self = this;
if (opts.type !== undefined && opts.type !== 'tile') {
return self.source.getAsync(opts);
}
const opts2 = Object.assign({}, opts);
return getSubTile().then(
res => {
if (opts2.z === opts.z || !res.data || res.data.length === 0) {
// this is exactly what we were asked for initially
return res;
}
if (!res.headers) {
res.headers = {};
}
// Extract portion of the higher zoom tile as a new tile
return core.uncompressAsync(res.data, res.headers).then(
pbf => core.extractSubTileAsync(pbf, opts.z, opts.x, opts.y, opts2.z, opts2.x, opts2.y)
).then(pbf => {
res.data = pbf;
res.headers.OverzoomFrom = opts2.z;
return res;
}).then( res => core.compressPbfAsync(res) );
});
function getSubTile() {
if (opts2.z < self.minzoom || opts2.z > self.maxzoom) {
Err.throwNoTile();
}
return Promise.try(() => {
return self.source.getAsync(opts2);
}).catch(err => {
if (opts2.z > self.minzoom && Err.isNoTileError(err)) {
// Tile is missing, zoom out and repeat
opts2.z = opts2.z - 1;
opts2.x = Math.floor(opts2.x / 2);
opts2.y = Math.floor(opts2.y / 2);
return getSubTile();
} else {
throw err;
}
});
}
});
OverZoomer.initKartotherian = function initKartotherian(cor) {
core = cor;
core.tilelive.protocols['overzoom:'] = OverZoomer;
};
module.exports = OverZoomer;