Created
July 15, 2015 19:07
-
-
Save nautilytics/75cbbb2d854de608e81c to your computer and use it in GitHub Desktop.
node-mapnik .pbf tile-server example
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
var config = require('../../config/database') | |
, _ = require('lodash-compat') | |
, mercator = require('./../../geo_utils/sphericalmercator') | |
, geographic = require('./../../geo_utils/geographic') | |
, crypto = require("crypto") | |
, zlib = require('zlib') | |
, mapnik = require('mapnik') | |
, utils = require('./../../config/utils'); | |
if (mapnik.register_default_input_plugins) | |
mapnik.register_default_input_plugins(); | |
var _geometry_field = 'geom' | |
, _table = 'us_county_500k' | |
, _fields = 'gid'; | |
var createPostGISConnectionDetails = function (table) { | |
return _.defaults({table: table, geometry_field: _geometry_field}, config.postGIS); | |
}; | |
module.exports = function (req, res) { | |
var bbox = mercator.xyz_to_envelope(+params.x, +params.y, +params.z, false); | |
// Create map | |
var map = new mapnik.Map(256, 256, mercator.proj4); | |
map.bufferSize = 10; // amount of edging provided for each tile rendered | |
// Create layer | |
var layer = new mapnik.Layer('tile', geographic.proj4); | |
var fieldTable = '(SELECT ' + [_geometry_field, _fields].join(',') + ' FROM ' + _table + ') AS "' + _table + '"'; | |
layer.datasource = new mapnik.Datasource(new createPostGISConnectionDetails(fieldTable)); | |
layer.styles = ['default']; | |
map.add_layer(layer); | |
var opts = {}; | |
// Use tolerance of 32 for zoom levels below max | |
var _maxzoom = 14; | |
opts.tolerance = +params.z < _maxzoom ? 32 : 0; | |
res.setHeader('Content-Type', 'application/x-protobuf'); | |
map.extent = bbox; | |
opts.buffer_size = map.bufferSize; | |
map.render(new mapnik.VectorTile(+params.z, +params.x, +params.y), opts, function (err, image) { | |
if (err || !image) { | |
res.removeHeader('Content-Encoding'); | |
res.writeHead(500, { | |
'Content-Type': 'application/x-protobuf' | |
}); | |
res.end(); | |
return; | |
} | |
// Fake empty RGBA | |
image.isSolid(function (err, solid, key) { | |
if (err) { | |
res.writeHead(500, { | |
'Content-Type': 'text/plain' | |
}); | |
res.end(err.message); | |
return; | |
} | |
// Solid handling. | |
var done = function (err, buffer) { | |
if (err) { | |
res.writeHead(500, { | |
'Content-Type': 'text/plain' | |
}); | |
res.end(err.message); | |
return; | |
} | |
if (solid === false) { | |
res.send(buffer); // return response | |
return; | |
} | |
// Empty tiles are equivalent to no tile. | |
if (!key) { | |
res.removeHeader('Content-Encoding'); | |
res.writeHead(404, { | |
'Content-Type': 'application/octet-stream' | |
}); | |
res.end(); //new Buffer('Tile is blank or does not exist', "utf-8") | |
return; | |
} | |
// Fake a hex code by md5ing the key. | |
var mockrgb = crypto.createHash('md5').update(buffer).digest('hex').substr(0, 6); | |
buffer.solid = [parseInt(mockrgb.substr(0, 2), 16), parseInt(mockrgb.substr(2, 2), 16), parseInt(mockrgb.substr(4, 2), 16), 1].join(','); | |
res.send(buffer); | |
}; | |
//Compress | |
res.setHeader('content-encoding', 'gzip'); | |
zlib.gzip(image.getData(), done); | |
}); | |
}); | |
}; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment