commit 7ba6f41ef4e8fe0f84dc54dae97e1fde2bf8159a
parent 4a3b9d6dd80123df34fa9d38b84097f431c2aad0
Author: Sergej Orlov <wladimirych@gmail.com>
Date: Thu, 5 May 2022 10:00:48 +0200
mapillary: Replace vector coverage layer with raster
Diffstat:
6 files changed, 6 insertions(+), 418 deletions(-)
diff --git a/src/config.js b/src/config.js
@@ -16,6 +16,7 @@ const config = {
geocachingSuUrl: 'https://nakarte.me/geocachingSu/geocaching_su2.json',
tracksStorageServer: 'https://tracks.nakarte.me',
wikimapiaTilesBaseUrl: 'https://proxy.nakarte.me/wikimapia/',
+ mapillaryRasterTilesUrl: 'https://mapillary.nakarte.me/{z}/{x}/{y}',
...secrets
};
diff --git a/src/lib/leaflet.control.panoramas/lib/mapillary/index.js b/src/lib/leaflet.control.panoramas/lib/mapillary/index.js
@@ -1,12 +1,15 @@
import L from 'leaflet';
-import {MapillaryCoverage} from './mapillary-coverage-layer';
import {fetch} from '~/lib/xhr-promise';
import config from '~/config';
import './style.css';
import {CloseButtonMixin, DateLabelMixin} from '../common';
function getCoverageLayer(options) {
- return new MapillaryCoverage(options);
+ return L.tileLayer(config.mapillaryRasterTilesUrl, L.extend({
+ tileSize: 1024,
+ zoomOffset: -2,
+ minNativeZoom: 0,
+ }, options));
}
async function getMapillary() {
diff --git a/src/lib/leaflet.control.panoramas/lib/mapillary/mapillary-coverage-layer.js b/src/lib/leaflet.control.panoramas/lib/mapillary/mapillary-coverage-layer.js
@@ -1,160 +0,0 @@
-import L from 'leaflet';
-import {MapillaryLoader} from './mapillary-loader';
-
-const MapillaryCoverage = L.GridLayer.extend({
- options: {
- tileSize: 1024,
- updateWhenIdle: true,
- color: '#00cfb1'
- },
-
- initialize: function(options) {
- L.GridLayer.prototype.initialize.call(this, options);
- this.loader = new MapillaryLoader(this.options.url, 12);
- },
-
- onAdd: function(map) {
- L.GridLayer.prototype.onAdd.call(this, map);
- this.on('tileunload', this.onTileUnload, this);
- },
-
- onRemove: function(map) {
- L.GridLayer.prototype.onRemove.call(this, map);
- this.off('tileunload', this.onTileUnload, this);
- },
-
- onTileUnload: function(e) {
- const tile = e.tile;
- tile._abortLoading();
- delete tile._tileData;
- delete tile._adjustment;
- },
-
- drawOverview: function(canvas) {
- const
- tileData = canvas._tileData;
- if (!tileData['mapillary-sequence-overview']) {
- return;
- }
- let {multiplier, offsetX, offsetY} = canvas._adjustment;
- const canvasCtx = canvas.getContext('2d');
- canvasCtx.fillStyle = this.options.color;
- for (let feature of tileData['mapillary-sequence-overview']) {
- if (feature.geometry.type !== 'Point') {
- throw new Error(`Invalid sequence overview geometry type "${feature.geometry.type}"`);
- }
- canvasCtx.beginPath();
- let x = feature.geometry.coordinates[0] * multiplier - offsetX;
- let y = feature.geometry.coordinates[1] * multiplier - offsetY;
- canvasCtx.arc(x, y, 5, 0, 2 * Math.PI);
- canvasCtx.fill();
- }
- },
-
- drawSequences: function(canvas, lineWidth) {
- let
- tileData = canvas._tileData,
- adjustment = canvas._adjustment;
-
- if (!tileData['mapillary-sequences']) {
- return;
- }
- const canvasCtx = canvas.getContext('2d');
- canvasCtx.beginPath();
- canvasCtx.strokeStyle = this.options.color;
- canvasCtx.lineWidth = lineWidth;
- // canvasCtx.lineWidth = thinLines ? 1 : 1;
- canvasCtx.lineCap = "round";
- canvasCtx.lineJoin = "bevel";
- for (let feature of tileData['mapillary-sequences']) {
- if (feature.geometry.type !== 'MultiLineString') {
- throw new Error(`Invalid sequence geometry type "${feature.geometry.type}"`);
- }
- let {multiplier, offsetX, offsetY} = adjustment;
-
- let lines = feature.geometry.coordinates;
- for (let lineI = 0; lineI < lines.length; lineI++) {
- let line = lines[lineI];
- if (!line.length) {
- continue;
- }
- let x = line[0][0] * multiplier - offsetX;
- let y = line[0][1] * multiplier - offsetY;
- canvasCtx.moveTo(x, y);
- if (line.length === 1) {
- canvasCtx.lineTo(x, y);
- }
- for (let pointI = 0; pointI < line.length; pointI++) {
- let x = line[pointI][0] * multiplier - offsetX;
- let y = line[pointI][1] * multiplier - offsetY;
- canvasCtx.lineTo(x, y);
- }
- }
- }
- canvasCtx.stroke();
- },
-
- drawImages: function(canvas) {
- let
- tileData = canvas._tileData,
- adjustment = canvas._adjustment;
- if (!tileData['mapillary-images']) {
- return;
- }
- let {multiplier, offsetX, offsetY} = adjustment;
- const canvasCtx = canvas.getContext('2d');
- canvasCtx.beginPath();
- canvasCtx.fillStyle = this.options.color;
- for (let feature of tileData['mapillary-images']) {
- if (feature.geometry.type !== 'Point') {
- throw new Error(`Invalid image geometry type "${feature.geometry.type}"`);
- }
- canvasCtx.beginPath();
- let x = feature.geometry.coordinates[0] * multiplier - offsetX;
- let y = feature.geometry.coordinates[1] * multiplier - offsetY;
- canvasCtx.arc(x, y, 4, 0, 2 * Math.PI);
- canvasCtx.fill();
- }
- },
-
- drawTile: function(canvas, coords) {
- if (!this._map) {
- return;
- }
- if (!canvas._tileData) {
- return;
- }
- if (coords.z < 6 + 2) {
- this.drawOverview(canvas);
- } else if (coords.z < 14 + 2) {
- let width = coords.z < 14 ? 10 : 5;
- this.drawSequences(canvas, width);
- } else {
- this.drawSequences(canvas, 2);
- this.drawImages(canvas);
- }
- },
-
- createTile: function(coords, done) {
- const canvas = L.DomUtil.create('canvas', 'leaflet-tile');
- canvas.width = this.options.tileSize;
- canvas.height = this.options.tileSize;
- let {dataPromise, abortLoading} = this.loader.requestTileData(coords);
- dataPromise.then((data) => {
- if (!data.error) {
- canvas._tileData = data.tileData;
- canvas._adjustment = data.adjustment || {multiplier: 1, offsetX: 0, offsetY: 0};
- setTimeout(() => {
- this.drawTile(canvas, coords);
- done(null, canvas);
- }, 1);
- }
- });
- canvas._abortLoading = abortLoading;
- return canvas;
- },
-
- }
-);
-
-export {MapillaryCoverage};
diff --git a/src/lib/leaflet.control.panoramas/lib/mapillary/mapillary-loader.js b/src/lib/leaflet.control.panoramas/lib/mapillary/mapillary-loader.js
@@ -1,87 +0,0 @@
-import L from 'leaflet';
-import {TiledDataLoader} from '~/lib/tiled-data-loader';
-import {decodeMvt} from './mvt';
-
-class MapillaryLoader extends TiledDataLoader {
- url = 'https://d25uarhxywzl1j.cloudfront.net/v0.1/{z}/{x}/{y}.mvt';
- maxZoom = 14;
-
- getTileUrl(coords) {
- const data = {
- x: coords.x,
- z: coords.z,
- y: coords.y
- };
- return L.Util.template(this.url, data);
- }
-
- layerTileToDataTileCoords(layerTileCoords) {
- let z = layerTileCoords.z - 2;
- let z2 = null;
- if (z > 6 && z <= 10) {
- z2 = 6;
- } else if (z >= 11 && z < 14) {
- z2 = z - 4;
- } else if (z < 0) {
- z2 = 0;
- } else if (z > this.maxZoom) {
- z2 = this.maxZoom;
- } else {
- return {z, x: layerTileCoords.x, y: layerTileCoords.y};
- }
-
- let multiplier = 1 << (z - z2);
- return {
- x: Math.floor(layerTileCoords.x / multiplier),
- y: Math.floor(layerTileCoords.y / multiplier),
- z: z2
- };
- }
-
- makeRequestData(dataTileCoords) {
- return {
- url: this.getTileUrl(dataTileCoords),
- options: {
- responseType: 'arraybuffer',
- timeout: 10000,
- isResponseSuccess: (xhr) => xhr.status === 200 || xhr.status === 403
- }
- };
- }
-
- calcAdjustment(layerTileCoords, dataTileCoords) {
- let adjustment = super.calcAdjustment(
- {x: layerTileCoords.x, y: layerTileCoords.y, z: layerTileCoords.z - 2},
- dataTileCoords
- );
- if (adjustment) {
- adjustment.offsetX *= 1024;
- adjustment.offsetY *= 1024;
- }
- return adjustment;
- }
-
- async processResponse(xhr, originalDataTileCoords) {
- return this._processResponse(xhr, originalDataTileCoords);
- }
-
- async _processResponse(xhr, originalDataTileCoords) {
- let tileData;
- if (xhr.status === 200 && xhr.response) {
- const layers = decodeMvt(xhr.response, 1024);
- tileData = {};
- for (let layer of layers) {
- tileData[layer.name] = layer.features;
- }
- } else {
- tileData = null;
- }
-
- return {
- tileData,
- coords: originalDataTileCoords
- };
- }
-}
-
-export {MapillaryLoader};
diff --git a/src/lib/leaflet.control.panoramas/lib/mapillary/mvt.js b/src/lib/leaflet.control.panoramas/lib/mapillary/mvt.js
@@ -1,123 +0,0 @@
-import Pbf from 'pbf';
-import {Tile as TileProto} from './vector_tile_pb';
-
-function decodeCoordinate(x) {
- return ((x >> 1) ^ (-(x & 1)));
-}
-
-function parseGeometry(geometryType, ints, coordinatesScale) { // eslint-disable-line complexity
- if (geometryType !== TileProto.GeomType.POINT && geometryType !== TileProto.GeomType.LINESTRING &&
- geometryType !== TileProto.GeomType.POLYGON) {
- throw new Error(`Unknown feature geometry type ${geometryType}`);
- }
- const len = ints.length;
- let pos = 0;
- const lineStrings = [];
- let line;
- let x = 0,
- y = 0;
- while (pos < len) {
- let i = ints[pos];
- let cmd = i & 0x7;
- let cmdRepeat = i >> 3;
- switch (cmd) {
- case 1: // MoveTo
- if (cmdRepeat !== 1) {
- throw new Error(`repeat=${cmdRepeat} for command MoveTo`);
- }
- if (pos + 2 > len) {
- throw new Error('Not enough elements for MoveTo arguments');
- }
- if (line) {
- lineStrings.push(line);
- }
- x += decodeCoordinate(ints[pos + 1]);
- y += decodeCoordinate(ints[pos + 2]);
- line = [[x * coordinatesScale, y * coordinatesScale]];
- pos += 3;
- break;
- case 2: // LineTo
- if (cmdRepeat < 1) {
- throw new Error(`repeat=${cmdRepeat} for command LineTo`);
- }
- if (!line) {
- throw new Error('LineTo with empty linestring');
- }
- pos += 1;
- for (let cmdN = 0; cmdN < cmdRepeat; cmdN++) {
- if (pos + 2 > len) {
- throw new Error('Not enough elements for LineTo arguments');
- }
- x += decodeCoordinate(ints[pos]);
- y += decodeCoordinate(ints[pos + 1]);
- line.push([x * coordinatesScale, y * coordinatesScale]);
- pos += 2;
- }
- break;
- case 7: // ClosePath
- if (geometryType !== TileProto.GeomType.POLYGON) {
- throw new Error(`ClosePath command for non-polygon type ${geometryType}`);
- }
- if (!line) {
- throw new Error('ClosePath with empty linestring');
- }
- if (cmdRepeat !== 1) {
- throw new Error(`ClosePath repeats ${cmdRepeat} times`);
- }
- line.push(line[0]);
- pos += 1;
- break;
- default:
- throw new Error(`Unknown command ${i} & 0x7 = ${cmd}`);
- }
- }
- if (line) {
- lineStrings.push(line);
- }
- const geometry = {};
- switch (geometryType) {
- case TileProto.GeomType.POINT:
- if (lineStrings.length !== 1 || lineStrings[0].length !== 1) {
- throw new Error('Invalid coordinates number for point');
- }
- geometry.type = 'Point';
- geometry.coordinates = lineStrings[0][0];
- break;
- case TileProto.GeomType.LINESTRING:
- geometry.type = 'MultiLineString';
- geometry.coordinates = lineStrings;
- break;
- case TileProto.GeomType.POLYGON:
- geometry.type = 'Polygon';
- geometry.coordinates = lineStrings;
- break;
- default:
- }
- return geometry;
-}
-
-function parseFeatures(layer, coordinatesScale) {
- const features = [];
- for (let feature of layer.features) {
- const geometry = parseGeometry(feature.type, feature.geometry, coordinatesScale);
- features.push({geometry});
- }
- return features;
-}
-
-function decodeMvt(ar, tileExtent = 256) {
- const
- pbf = new Pbf(new Uint8Array(ar)),
- tileData = TileProto.read(pbf);
- const parsedLayers = [];
- for (let layer of tileData.layers) {
- let scale = tileExtent / layer.extent;
- parsedLayers.push({
- name: layer.name,
- features: parseFeatures(layer, scale)
- });
- }
- return parsedLayers;
-}
-
-export {decodeMvt};
diff --git a/src/lib/leaflet.control.panoramas/lib/mapillary/vector_tile_pb.js b/src/lib/leaflet.control.panoramas/lib/mapillary/vector_tile_pb.js
@@ -1,46 +0,0 @@
-// code generated by pbf v3.0.5
-
-// Tile ========================================
-
-var Tile = exports.Tile = {};
-
-Tile.read = function (pbf, end) {
- return pbf.readFields(Tile._readField, {layers: []}, end);
-};
-Tile._readField = function (tag, obj, pbf) {
- if (tag === 3) obj.layers.push(Tile.Layer.read(pbf, pbf.readVarint() + pbf.pos));
-};
-
-Tile.GeomType = {
- "UNKNOWN": 0,
- "POINT": 1,
- "LINESTRING": 2,
- "POLYGON": 3
-};
-
-
-// Tile.Feature ========================================
-
-Tile.Feature = {};
-
-Tile.Feature.read = function (pbf, end) {
- return pbf.readFields(Tile.Feature._readField, {id: 0, tags: [], type: 0, geometry: []}, end);
-};
-Tile.Feature._readField = function (tag, obj, pbf) {
- if (tag === 3) obj.type = pbf.readVarint();
- else if (tag === 4) pbf.readPackedVarint(obj.geometry);
-};
-
-// Tile.Layer ========================================
-
-Tile.Layer = {};
-
-Tile.Layer.read = function (pbf, end) {
- return pbf.readFields(Tile.Layer._readField, {version: 0, name: "", features: [], keys: [], values: [], extent: 0}, end);
-};
-Tile.Layer._readField = function (tag, obj, pbf) {
- if (tag === 15) obj.version = pbf.readVarint();
- else if (tag === 1) obj.name = pbf.readString();
- else if (tag === 2) obj.features.push(Tile.Feature.read(pbf, pbf.readVarint() + pbf.pos));
- else if (tag === 5) obj.extent = pbf.readVarint();
-};