fix: 512 tiles being wrong level for maplibre-js

Signed-off-by: Andrew Calcutt <acalcutt@techidiots.net>
This commit is contained in:
Andrew Calcutt 2024-01-28 22:30:36 -05:00
parent 90100e79d9
commit 5e8288cceb
2 changed files with 43 additions and 34 deletions

View file

@ -108,6 +108,7 @@
for (tile_url in tile_urls) { for (tile_url in tile_urls) {
L.tileLayer(tile_urls[tile_url], { L.tileLayer(tile_urls[tile_url], {
tileSize: 512, tileSize: 512,
zoomOffset: -1,
minZoom: tile_minzoom, minZoom: tile_minzoom,
maxZoom: tile_maxzoom, maxZoom: tile_maxzoom,
attribution: tile_attribution attribution: tile_attribution

View file

@ -48,7 +48,8 @@ const PATH_PATTERN =
/^((fill|stroke|width)\:[^\|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)/; /^((fill|stroke|width)\:[^\|]+\|)*(enc:.+|-?\d+(\.\d*)?,-?\d+(\.\d*)?(\|-?\d+(\.\d*)?,-?\d+(\.\d*)?)+)/;
const httpTester = /^(http(s)?:)?\/\//; const httpTester = /^(http(s)?:)?\/\//;
const mercator = new SphericalMercator(); const mercator_256 = new SphericalMercator();
const mercator_512 = new SphericalMercator({size: 512});
const getScale = (scale) => (scale || '@1x').slice(1, 2) | 0; const getScale = (scale) => (scale || '@1x').slice(1, 2) | 0;
mlgl.on('message', (e) => { mlgl.on('message', (e) => {
@ -348,8 +349,8 @@ const calcZForBBox = (bbox, w, h, query) => {
const padding = query.padding !== undefined ? parseFloat(query.padding) : 0.1; const padding = query.padding !== undefined ? parseFloat(query.padding) : 0.1;
const minCorner = mercator.px([bbox[0], bbox[3]], z); const minCorner = mercator_256.px([bbox[0], bbox[3]], z);
const maxCorner = mercator.px([bbox[2], bbox[1]], z); const maxCorner = mercator_256.px([bbox[2], bbox[1]], z);
const w_ = w / (1 + 2 * padding); const w_ = w / (1 + 2 * padding);
const h_ = h / (1 + 2 * padding); const h_ = h / (1 + 2 * padding);
@ -380,14 +381,6 @@ const respondImage = (
overlay = null, overlay = null,
mode = 'tile', mode = 'tile',
) => { ) => {
if (
Math.abs(lon) > 180 ||
Math.abs(lat) > 85.06 ||
lon !== lon ||
lat !== lat
) {
return res.status(400).send('Invalid center');
}
if ( if (
Math.min(width, height) <= 0 || Math.min(width, height) <= 0 ||
@ -413,7 +406,15 @@ const respondImage = (
pool = item.map.renderersStatic[scale]; pool = item.map.renderersStatic[scale];
} }
pool.acquire((err, renderer) => { pool.acquire((err, renderer) => {
const mlglZ = Math.max(0, z - 1);
// For 512px tiles, use the actual maplibre-native zoom. For 256px tiles, use zoom - 1
let mlglZ
if (width === 512) {
mlglZ = Math.max(0, z);
} else {
mlglZ = Math.max(0, z - 1);
}
const params = { const params = {
zoom: mlglZ, zoom: mlglZ,
center: [lon, lat], center: [lon, lat],
@ -423,12 +424,14 @@ const respondImage = (
height, height,
}; };
if (z === 0) { // HACK(Part 1) to allow for zoom 0 256px images. (z - 1) used byt 256 tiles would be -1, which isn't support. Instead a double size image is requested from zoom 0 and it is later resized.
if (z === 0 && width === 256) {
params.width *= 2; params.width *= 2;
params.height *= 2; params.height *= 2;
} }
// END HACK(Part 1)
if (z > 2 && tileMargin > 0) { if (((z > 2 && width === 256) || (z > 1 && width === 512)) && tileMargin > 0) {
params.width += tileMargin * 2; params.width += tileMargin * 2;
params.height += tileMargin * 2; params.height += tileMargin * 2;
} }
@ -449,12 +452,16 @@ const respondImage = (
}, },
}); });
if (z > 2 && tileMargin > 0) { if (((z > 2 && width === 256) || (z > 1 && width === 512)) && tileMargin > 0) {
const [_, y] = mercator.px(params.center, z); let y
let yoffset = Math.max( let yoffset
Math.min(0, y - 128 - tileMargin), if (width === 512) {
y + 128 + tileMargin - Math.pow(2, z + 8), y = mercator_512.px(params.center, z)[1]
); yoffset = Math.max(Math.min(0, y - 256 - tileMargin), y + 256 + tileMargin - Math.pow(2, z + 8));
} else {
y = mercator_256.px(params.center, z)[1]
yoffset = Math.max(Math.min(0, y - 128 - tileMargin), y + 128 + tileMargin - Math.pow(2, z + 8));
}
image.extract({ image.extract({
left: tileMargin * scale, left: tileMargin * scale,
top: (tileMargin + yoffset) * scale, top: (tileMargin + yoffset) * scale,
@ -463,10 +470,11 @@ const respondImage = (
}); });
} }
if (z === 0) { // HACK(Part 2) to allow for zoom 0 256px images. (z - 1) used byt 256 tiles would be -1, which isn't support. Instead a double size image is requested from zoom 0 and it is resized here.
// HACK: when serving zoom 0, resize the 0 tile from 512 to 256 if ((z === 0 && width === 256)) {
image.resize(width * scale, height * scale); image.resize(width * scale, height * scale);
} }
// END HACK(Part 2)
const composites = []; const composites = [];
if (overlay) { if (overlay) {
@ -564,13 +572,13 @@ export const serve_rendered = {
) { ) {
return res.status(404).send('Out of bounds'); return res.status(404).send('Out of bounds');
} }
const tileCenter = mercator.ll(
[ let tileCenter
((x + 0.5) / (1 << z)) * (tileSize << z), if (tileSize === 512) {
((y + 0.5) / (1 << z)) * (tileSize << z), tileCenter = mercator_512.ll([((x + 0.5) / (1 << z)) * (tileSize << z),((y + 0.5) / (1 << z)) * (tileSize << z)],z);
], } else {
z, tileCenter = mercator_256.ll([((x + 0.5) / (1 << z)) * (tileSize << z),((y + 0.5) / (1 << z)) * (tileSize << z)],z);
); }
// prettier-ignore // prettier-ignore
return respondImage( return respondImage(
@ -615,7 +623,7 @@ export const serve_rendered = {
} }
const transformer = raw const transformer = raw
? mercator.inverse.bind(mercator) ? mercator_256.inverse.bind(mercator)
: item.dataProjWGStoInternalWGS; : item.dataProjWGStoInternalWGS;
if (transformer) { if (transformer) {
@ -662,7 +670,7 @@ export const serve_rendered = {
let center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2]; let center = [(bbox[0] + bbox[2]) / 2, (bbox[1] + bbox[3]) / 2];
const transformer = raw const transformer = raw
? mercator.inverse.bind(mercator) ? mercator_256.inverse.bind(mercator)
: item.dataProjWGStoInternalWGS; : item.dataProjWGStoInternalWGS;
if (transformer) { if (transformer) {
@ -758,7 +766,7 @@ export const serve_rendered = {
const format = req.params.format; const format = req.params.format;
const transformer = raw const transformer = raw
? mercator.inverse.bind(mercator) ? mercator_256.inverse.bind(mercator)
: item.dataProjWGStoInternalWGS; : item.dataProjWGStoInternalWGS;
const paths = extractPathsFromQuery(req.query, transformer); const paths = extractPathsFromQuery(req.query, transformer);
@ -790,8 +798,8 @@ export const serve_rendered = {
bbox[3] = Math.max(bbox[3], pair[1]); bbox[3] = Math.max(bbox[3], pair[1]);
} }
const bbox_ = mercator.convert(bbox, '900913'); const bbox_ = mercator_256.convert(bbox, '900913');
const center = mercator.inverse([ const center = mercator_256.inverse([
(bbox_[0] + bbox_[2]) / 2, (bbox_[0] + bbox_[2]) / 2,
(bbox_[1] + bbox_[3]) / 2, (bbox_[1] + bbox_[3]) / 2,
]); ]);