diff --git a/public/templates/viewer.tmpl b/public/templates/viewer.tmpl index 5f81eae..82a0a37 100644 --- a/public/templates/viewer.tmpl +++ b/public/templates/viewer.tmpl @@ -107,6 +107,7 @@ for (tile_url in tile_urls) { L.tileLayer(tile_urls[tile_url], { + tileSize: 512, minZoom: tile_minzoom, maxZoom: tile_maxzoom, attribution: tile_attribution diff --git a/src/serve_data.js b/src/serve_data.js index 4a95b1f..b282c86 100644 --- a/src/serve_data.js +++ b/src/serve_data.js @@ -169,6 +169,7 @@ export const serve_data = { ); app.get('/:id.json', (req, res, next) => { + const tileSize = undefined; const item = repo[req.params.id]; if (!item) { return res.sendStatus(404); @@ -178,6 +179,7 @@ export const serve_data = { req, info.tiles, `data/${req.params.id}`, + tileSize, info.format, item.publicUrl, { diff --git a/src/serve_rendered.js b/src/serve_rendered.js index ec590b6..0e1260b 100644 --- a/src/serve_rendered.js +++ b/src/serve_rendered.js @@ -552,6 +552,7 @@ export const serve_rendered = { const y = req.params.y | 0; const scale = getScale(req.params.scale); const format = req.params.format; + const tileSize = 256; if ( z < 0 || x < 0 || @@ -562,11 +563,58 @@ export const serve_rendered = { ) { return res.status(404).send('Out of bounds'); } - const tileSize = 256; const tileCenter = mercator.ll( [ - ((x + 0.5) / (1 << z)) * (256 << z), - ((y + 0.5) / (1 << z)) * (256 << z), + ((x + 0.5) / (1 << z)) * (tileSize << z), + ((y + 0.5) / (1 << z)) * (tileSize << z), + ], + z, + ); + + // prettier-ignore + return respondImage( + options, item, z, tileCenter[0], tileCenter[1], 0, 0, tileSize, tileSize, scale, format, res, + ); + }, + ); + + app.get( + `/:id/:tileSize(256|512)/:z(\\d+)/:x(\\d+)/:y(\\d+):scale(${scalePattern})?.:format([\\w]+)`, + (req, res, next) => { + const item = repo[req.params.id]; + if (!item) { + return res.sendStatus(404); + } + + const modifiedSince = req.get('if-modified-since'); + const cc = req.get('cache-control'); + if (modifiedSince && (!cc || cc.indexOf('no-cache') === -1)) { + if (new Date(item.lastModified) <= new Date(modifiedSince)) { + return res.sendStatus(304); + } + } + + const z = req.params.z | 0; + const x = req.params.x | 0; + const y = req.params.y | 0; + const scale = getScale(req.params.scale); + const format = req.params.format; + const tileSize = parseInt(req.params.tileSize, 10) || 256; + console.log(tileSize); + if ( + z < 0 || + x < 0 || + y < 0 || + z > 22 || + x >= Math.pow(2, z) || + y >= Math.pow(2, z) + ) { + return res.status(404).send('Out of bounds'); + } + const tileCenter = mercator.ll( + [ + ((x + 0.5) / (1 << z)) * (tileSize << z), + ((y + 0.5) / (1 << z)) * (tileSize << z), ], z, ); @@ -822,6 +870,7 @@ export const serve_rendered = { } app.get('/:id.json', (req, res, next) => { + const tileSize = 512; const item = repo[req.params.id]; if (!item) { return res.sendStatus(404); @@ -831,6 +880,7 @@ export const serve_rendered = { req, info.tiles, `styles/${req.params.id}`, + tileSize, info.format, item.publicUrl, ); diff --git a/src/server.js b/src/server.js index 2b382a0..465b0e5 100644 --- a/src/server.js +++ b/src/server.js @@ -356,6 +356,7 @@ function start(opts) { const addTileJSONs = (arr, req, type) => { for (const id of Object.keys(serving[type])) { + const tileSize = 256; const info = clone(serving[type][id].tileJSON); let path = ''; if (type === 'rendered') { @@ -367,6 +368,7 @@ function start(opts) { req, info.tiles, path, + tileSize, info.format, opts.publicUrl, { @@ -452,6 +454,7 @@ function start(opts) { }; if (style.serving_rendered) { + const tileSize = 256; const { center } = style.serving_rendered.tileJSON; if (center) { style.viewer_hash = `#${center[2]}/${center[1].toFixed( @@ -468,6 +471,7 @@ function start(opts) { req, style.serving_rendered.tileJSON.tiles, `styles/${id}`, + tileSize, style.serving_rendered.tileJSON.format, opts.publicUrl, )[0]; @@ -491,17 +495,19 @@ function start(opts) { data.is_vector = tileJSON.format === 'pbf'; if (!data.is_vector) { + const tileSize = 256; if (center) { const centerPx = mercator.px([center[0], center[1]], center[2]); data.thumbnail = `${center[2]}/${Math.floor( centerPx[0] / 256, - )}/${Math.floor(centerPx[1] / 256)}.${tileJSON.format}`; + )}/${Math.floor(centerPx[1] / tileSize)}.${tileJSON.format}`; } data.xyz_link = getTileUrls( req, tileJSON.tiles, `data/${id}`, + tileSize, tileJSON.format, opts.publicUrl, { diff --git a/src/utils.js b/src/utils.js index 4fdf43a..c3b23b4 100644 --- a/src/utils.js +++ b/src/utils.js @@ -26,7 +26,7 @@ export const getPublicUrl = (publicUrl, req) => { return getUrlObject(req).toString(); }; -export const getTileUrls = (req, domains, path, format, publicUrl, aliases) => { +export const getTileUrls = (req, domains, path, tileSize, format, publicUrl, aliases) => { const urlObject = getUrlObject(req); if (domains) { if (domains.constructor === String && domains.length > 0) { @@ -67,15 +67,20 @@ export const getTileUrls = (req, domains, path, format, publicUrl, aliases) => { format = aliases[format]; } + let tileParams = '{z}/{x}/{y}'; + if (['png', 'jpg', 'jpeg', 'webp'].includes(format) && tileSize) { + tileParams = `${tileSize}/{z}/{x}/{y}`; + } + const uris = []; if (!publicUrl) { for (const domain of domains) { uris.push( - `${req.protocol}://${domain}/${path}/{z}/{x}/{y}.${format}${query}`, + `${req.protocol}://${domain}/${path}/${tileParams}.${format}${query}`, ); } } else { - uris.push(`${publicUrl}${path}/{z}/{x}/{y}.${format}${query}`); + uris.push(`${publicUrl}${path}/${tileParams}.${format}${query}`); } return uris;