From 275b4860564f9318619adf91910189412b3e0856 Mon Sep 17 00:00:00 2001 From: LEinfeldt Date: Sun, 15 Mar 2020 13:29:37 +0100 Subject: [PATCH] Add marker query parameter for static maps --- public/resources/images/markerImage.png | Bin 0 -> 3629 bytes src/serve_rendered.js | 115 ++++++++++++++++++------ 2 files changed, 90 insertions(+), 25 deletions(-) create mode 100644 public/resources/images/markerImage.png diff --git a/public/resources/images/markerImage.png b/public/resources/images/markerImage.png new file mode 100644 index 0000000000000000000000000000000000000000..07c1e0395e6e6d5f491e7fa8e2375f196fbb6a9a GIT binary patch literal 3629 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 { const pathParts = (query.path || '').split('|'); const path = []; for (const pair of pathParts) { - const pairParts = pair.split(','); - if (pairParts.length === 2) { - let pair; - if (query.latlng === '1' || query.latlng === 'true') { - pair = [+(pairParts[1]), +(pairParts[0])]; - } else { - pair = [+(pairParts[0]), +(pairParts[1])]; - } - if (transformer) { - pair = transformer(pair); - } - path.push(pair); + path.push(splitCoordinatePair(pair, query, transformer)); } - } return path; }; -const renderOverlay = (z, x, y, bearing, pitch, w, h, scale, - path, query) => { - if (!path || path.length < 2) { - return null; - } - const precisePx = (ll, zoom) => { - const px = mercator.px(ll, 20); - const scale = Math.pow(2, zoom - 20); - return [px[0] * scale, px[1] * scale]; - }; +const extractMarkerFromQuery = (query, transformer) => { - const center = precisePx([x, y], z); + const markerPositions = []; + + const markerParts = (query.markers || query.marker || '').split('|'); + + if(query.marker && markerParts[0] === 'center') {return null;} + + markerParts.forEach(marker => { + markerPositions.push(splitCoordinatePair(marker,query,transformer)); + }); + + return markerPositions; +}; + +const splitCoordinatePair = (pair, query, transformer) => { + const pairParts = pair.split(','); + if (pairParts.length === 2) { + let coordinatePair; + if (query.latlng === '1' || query.latlng === 'true') { + coordinatePair = [+(pairParts[1]), +(pairParts[0])]; + } else { + coordinatePair = [+(pairParts[0]), +(pairParts[1])]; + } + if (transformer) { + coordinatePair = transformer(coordinatePair); + } + return coordinatePair; + } +} + +const precisePx = (ll, zoom) => { + const px = mercator.px(ll, 20); + const scale = Math.pow(2, zoom - 20); + return [px[0] * scale, px[1] * scale]; +}; + +const georeferenceMapCenter = (x, y, z, h) => { + let center = precisePx([x, y], z); const mapHeight = 512 * (1 << z); const maxEdge = center[1] + h / 2; @@ -140,6 +155,49 @@ const renderOverlay = (z, x, y, bearing, pitch, w, h, scale, center[1] -= minEdge; } + return center; +}; + +const renderMarkerOverlay = (x, y, z, w, h, scale, marker) => { + const center = georeferenceMapCenter(x, y, z, h); + + const canvas = createCanvas(scale * w, scale * h); + + const markers = []; + + marker.forEach(m => { + markers.push(precisePx(m,z)); + }) + + const ctx = canvas.getContext('2d'); + ctx.scale(scale, scale); + ctx.translate(-center[0] + w / 2, -center[1] + h / 2); + + try { + const imageFile = fs.readFileSync(__dirname + '/../public/resources/images/markerImage.png'); + const markerImage = new Image; + markerImage.src = imageFile; + + markers.forEach(marker => { + ctx.drawImage(markerImage, marker[0] - (markerImage.width / 2) * 0.2, marker[1] - (markerImage.height) * 0.2, markerImage.width * 0.2, markerImage.height * 0.2) + }) + ctx.fill(); + ctx.stroke(); + } + catch(e) { + console.log('Errorloading marker image', e); + } + return canvas.toBuffer(); +}; + +const renderOverlay = (z, x, y, bearing, pitch, w, h, scale, + path, query) => { + if (!path || path.length < 2) { + return null; + } + + const center = georeferenceMapCenter(x, y, z,h); + const canvas = createCanvas(scale * w, scale * h); const ctx = canvas.getContext('2d'); ctx.scale(scale, scale); @@ -425,6 +483,13 @@ module.exports = { y = ll[1]; } + if(req.query.marker || req.query.markers) { + let markers = extractMarkerFromQuery(req.query, transformer); + markers = markers === null ? [[x,y]] : markers; + const overlay = renderMarkerOverlay(x, y, z, w, h, scale, markers); + return respondImage(item, z, x, y, bearing, pitch, w, h, scale, format, res, next, overlay); + } + const path = extractPathFromQuery(req.query, transformer); const overlay = renderOverlay(z, x, y, bearing, pitch, w, h, scale, path, req.query);