-
Notifications
You must be signed in to change notification settings - Fork 8
/
index.js
123 lines (117 loc) · 3.43 KB
/
index.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
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
var geojsonvt = require('geojson-vt');
var vtpbf = require('vt-pbf');
var GeoJSONWrapper = vtpbf.GeoJSONWrapper;
var SphericalMercator = require('@mapbox/sphericalmercator');
var VectorTilesGenerator = function(options) {
this.projection = new SphericalMercator({
size: 256
});
this.pgPool = options.pgPool;
this.cacheOptions = options.cache;
};
VectorTilesGenerator.prototype.tile = function(opts) {
var tile = {
x: opts.x,
y: opts.y,
z: opts.z
};
tile.bounds = this.projection.bbox(opts.x, opts.y, opts.z, false, '900913');
tile.bbox = [
'ST_SetSRID(',
'ST_MakeBox2D(',
'ST_MakePoint(', tile.bounds[0], ', ', tile.bounds[1], '), ',
'ST_MakePoint(', tile.bounds[2], ', ', tile.bounds[3], ')',
'), ',
'3857',
')'
].join('');
tile.bbox_4326 = 'ST_Transform('+tile.bbox+', 4326)';
tile.geom_hash = 'Substr(MD5(ST_AsBinary(the_geom)), 1, 10)';
return tile;
};
VectorTilesGenerator.prototype.performQuery = function(sql, tile) {
//replacing patterns between two '!' like !bbox!
var templatePattern = /!([0-9a-zA-Z_\-]+)!/g;
sql = sql.replace(templatePattern, function(match){
match = match.substr(1, match.length-2);
return tile[match];
});
//actually performing query
return this.pgPool.connect()
.then(function(client) {
return client.query(sql)
.then(function(result){
client.release();
return result.rows;
})
.catch(function(e){
client.release();
throw e;
});
});
};
VectorTilesGenerator.prototype.queryResultsToGeoJSON = function(queryResultsRows) {
var features = queryResultsRows.map(function(elt){
var properties = {};
for (var attribute in elt) {
if (attribute !== 'the_geom_geojson') {
properties[attribute] = elt[attribute];
}
}
return {
type: 'Feature',
geometry: JSON.parse(elt.the_geom_geojson),
properties: properties
};
});
var geojson = {
type: 'FeatureCollection',
features: features
};
return Promise.resolve(geojson);
};
VectorTilesGenerator.prototype.get = function(queries, opts) {
var self = this;
var tile = this.tile(opts);
return Promise.all(Object.keys(queries).map(function(key){
var sql = queries[key];
return self.performQuery(sql, tile)
.then(function(queryResultsRows){
return self.queryResultsToGeoJSON(queryResultsRows)
.then(function(geojson){
var govt = geojsonvt(geojson, {
maxZoom: opts.z+1,
indexMaxZoom: opts.z-1
});
var pbf = govt.getTile(opts.z, opts.x, opts.y);
return {
name: key,
geojson: geojson,
pbf: pbf
};
});
});
}))
.then(function(layers) {
var pbfOptions = {};
for(var i in layers) {
var layer = layers[i];
if(layer.pbf){
//construct the GeoJSONWrapper here, so that we can tell him the version !
pbfOptions[layer.name] = new GeoJSONWrapper(layer.pbf.features);
pbfOptions[layer.name].name = layer.name;
pbfOptions[layer.name].version = 2;
}
}
if(pbfOptions.length === 0) {
return undefined;
}
// we use fromVectorTileJs instead of fromGeojsonVt because we constructed the GeoJSONWrapper ourselves
var buff = vtpbf.fromVectorTileJs({layers: pbfOptions});
if(buff) {
buff = new Buffer(buff.buffer);
}
return buff;
});
};
module.exports = VectorTilesGenerator;