commit 5897c861e1eed55b3efc6f350c73a7a9de402590
parent 199d71b4223e0e051abbdf25b50396c9f66f2b64
Author: Sergej Orlov <wladimirych@gmail.com>
Date: Tue, 31 Jan 2017 00:03:12 +0300
[wikimapia] use new loader module
Diffstat:
7 files changed, 393 insertions(+), 355 deletions(-)
diff --git a/src/layers.js b/src/layers.js
@@ -7,6 +7,7 @@ import 'lib/leaflet.layer.soviet-topomaps-grid';
import 'lib/leaflet.layer.westraPasses';
import 'lib/leaflet.layer.nordeskart';
import 'lib/leaflet.layer.tracks-collection';
+import 'lib/leaflet.layer.wikimapia';
export default function getLayers() {
const layers = [
@@ -195,13 +196,13 @@ export default function getLayers() {
isDefault: true,
layer: new L.Layer.SovietTopoGrid({code: 'Ng'})
},
- // {
- // title: 'Wikimapia',
- // order: 1130,
- // isOverlay: true,
- // isDefault: true,
- // layer: new L.Wikimapia({code: 'W', zIndexOffset: 10000}),
- // },
+ {
+ title: 'Wikimapia',
+ order: 1130,
+ isOverlay: true,
+ isDefault: true,
+ layer: new L.Wikimapia({code: 'W'}),
+ },
{
title: 'Mountain passes (Westra)',
order: 1140,
diff --git a/src/lib/leaflet.layer.wikimapia/index.js b/src/lib/leaflet.layer.wikimapia/index.js
@@ -0,0 +1,207 @@
+import L from 'leaflet';
+import {WikimapiaLoader} from './wikimapia-loader';
+import './style.css';
+
+
+function isPointInPolygon(polygon, p) {
+ var inside = false;
+ var prevNode = polygon[polygon.length - 1],
+ node, i;
+ for (i = 0; i < polygon.length; i++) {
+ node = polygon[i];
+ if (
+ ((node[0] <= p[0] && p[0] < prevNode[0]) || prevNode[0] <= p[0] && p[0] < node[0]) &&
+ p[1] < (prevNode[1] - node[1]) * (p[0] - node[0]) / (prevNode[0] - node[0]) + node[1]
+ ) {
+ inside = !inside;
+ }
+ prevNode = node;
+ }
+ return inside;
+}
+
+L.Wikimapia = L.GridLayer.extend({
+ options: {
+ tileSize: 1024,
+ updateWhenIdle: true,
+ },
+
+ initialize: function(options) {
+ L.GridLayer.prototype.initialize.call(this, options);
+ this.loader = null;
+ },
+
+ onAdd: function(map) {
+ if (!this.loader) {
+ this.loader = new WikimapiaLoader(map.project.bind(map));
+ }
+ L.GridLayer.prototype.onAdd.call(this, map);
+ this.on('tileunload', this.onTileUnload, this);
+ map.on('mousemove', this.onMouseMove, this);
+ map.on('click', this.onClick, this);
+ },
+
+ onRemove: function(map) {
+ map.off('mousemove', this.onMouseMove, this);
+ map.off('click', this.onClick, this);
+ if (this.highlightedPlace) {
+ this._map.removeLayer(this.highlightedPlace.polygon);
+ this._map.removeLayer(this.highlightedPlace.label);
+ this.highlightedPlace = null;
+ }
+ L.TileLayer.prototype.onRemove.call(this, map);
+ this.off('tileunload', this.onTileUnload, this);
+
+ },
+
+ drawTile: function(canvas) {
+ if (!this._map) {
+ return;
+ }
+ const
+ tileData = canvas._tileData,
+ adjustment = canvas._adjustment;
+ if (!tileData) {
+ return;
+ }
+
+ const canvasCtx = canvas.getContext('2d');
+ canvasCtx.beginPath();
+ canvasCtx.strokeStyle = '#CFA600';
+ canvasCtx.lineWidth = 1;
+ for (let place of tileData.places) {
+ let polygon = place.localPolygon;
+ if (!polygon) {
+ continue;
+ }
+ if (adjustment) {
+ let {multiplier, offsetX, offsetY} = adjustment,
+ polygon2 = [];
+ for (let i = 0; i < polygon.length; i++) {
+ let p = polygon[i];
+ polygon2.push({
+ x: p.x * multiplier - offsetX,
+ y: p.y * multiplier - offsetY
+ }
+ );
+ }
+ polygon = polygon2;
+ }
+ canvasCtx.moveTo(polygon[0].x, polygon[0].y);
+ let p;
+ for (let i = 1; i < polygon.length; i++) {
+ p = polygon[i];
+ canvasCtx.lineTo(p.x, p.y);
+ }
+ canvasCtx.lineTo(polygon[0].x, polygon[0].y);
+ }
+ canvasCtx.stroke();
+
+ },
+
+ 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) => {
+ canvas._tileData = data.tileData;
+ canvas._adjustment = data.adjustment;
+ this.drawTile(canvas);
+ this._tileOnLoad(done, canvas)
+ }
+ );
+
+ canvas._abortLoading = abortLoading;
+ return canvas;
+ },
+
+ _tileOnLoad: function(done, tile) {
+ // For https://github.com/Leaflet/Leaflet/issues/3332
+ if (L.Browser.ielt9) {
+ setTimeout(L.bind(done, this, null, tile), 0);
+ } else {
+ done(null, tile);
+ }
+ },
+
+ onTileUnload: function(e) {
+ const tile = e.tile;
+ tile._abortLoading();
+ delete tile._tileData;
+ delete tile._adjustment;
+ },
+
+ _tileCoordsFromEvent: function(e) {
+ const layerPoint = this._map.getPixelOrigin().add(e.layerPoint);
+ const tileSize = this.options.tileSize;
+ let coords = {
+ x: Math.floor(layerPoint.x / tileSize),
+ y: Math.floor(layerPoint.y / tileSize),
+ z: this._map.getZoom()
+ };
+
+ return coords;
+ },
+
+ getPlaceAtMousePos: function(e) {
+ const tileCoords = this._tileCoordsFromEvent(e);
+ let tile = this._tiles[this._tileCoordsToKey(tileCoords)];
+ if (!tile) {
+ return null;
+ }
+ const tileData = tile.el._tileData;
+ if (!tileData) {
+ return null;
+ }
+ return this.getPlaceAtLatlng(e.latlng, tileData.places);
+ },
+
+ onMouseMove: function(e) {
+ const place = this.getPlaceAtMousePos(e);
+ if (this.highlightedPlace && (!place || this.highlightedPlace.id != place.id)) {
+ this._map.removeLayer(this.highlightedPlace.polygon);
+ this._map.removeLayer(this.highlightedPlace.label);
+ this.highlightedPlace = null;
+ }
+
+ if (place && !this.highlightedPlace) {
+ this.highlightedPlace = {
+ id: place.id,
+ polygon: L.polygon(place.polygon, {
+ weight: 0,
+ color: '#E6B800'
+ }
+ ),
+ label: L.tooltip({className: 'wikimapia-tooltip'}, null)
+ };
+ this.highlightedPlace.label.setLatLng(e.latlng);
+ this.highlightedPlace.polygon.addTo(this._map);
+ this.highlightedPlace.label.setContent(place.title);
+ this._map.addLayer(this.highlightedPlace.label);
+ }
+ if (this.highlightedPlace) {
+ this.highlightedPlace.label.setLatLng(e.latlng);
+ }
+ },
+
+ onClick: function(e) {
+
+ },
+
+ getPlaceAtLatlng: function(latlng, places) {
+ let {lat, lng} = latlng,
+ bounds, place;
+ for (let i = places.length - 1; i >= 0; i--) {
+ place = places[i];
+ bounds = place.boundsWESN;
+ if (lng >= bounds[0] && lng <= bounds[1] && lat >= bounds[2] && lat <= bounds[3] &&
+ isPointInPolygon(place.polygon, [lat, lng])) {
+ return place;
+ }
+ }
+ }
+
+ }
+);
diff --git a/src/lib/leaflet.layer.wikimapia/style.css b/src/lib/leaflet.layer.wikimapia/style.css
@@ -10,4 +10,14 @@
z-index: 10000;
max-width: 500px;
box-sizing: border-box;
-}
-\ No newline at end of file
+ margin-top: -6px;
+ /*box-shadow: none !important;*/
+}
+
+.wikimapia-tooltip:before {
+ border: none !important;
+}
+
+.leaflet-tooltip-right {
+ margin-left: 16px !important;
+}
diff --git a/src/lib/leaflet.layer.wikimapia/wikimapia-loader.js b/src/lib/leaflet.layer.wikimapia/wikimapia-loader.js
@@ -0,0 +1,80 @@
+import {TiledDataLoader} from 'lib/tiled-data-loader';
+import wmUtils from './wm-utils'
+import urlViaCorsProxy from 'lib/CORSProxy';
+
+class WikimapiaLoader extends TiledDataLoader {
+ maxZoom = 15;
+ tileSize = 1024;
+
+ constructor(projectFunc) {
+ super();
+ this._project = projectFunc;
+
+ }
+
+ getFromCache(dataTileCoords) {
+ dataTileCoords = Object.assign({}, dataTileCoords);
+ let exactMatch = true;
+ while (dataTileCoords.z >= 0) {
+ let key = this.makeTileKey(dataTileCoords);
+ let res = this._cache.get(key);
+ if (res.found) {
+ if (exactMatch || !res.value.hasChildren) {
+ res['coords'] = dataTileCoords;
+ return res;
+ }
+ break;
+ }
+ dataTileCoords.z -= 1;
+ dataTileCoords.x = Math.floor(dataTileCoords.x / 2);
+ dataTileCoords.y = Math.floor(dataTileCoords.y / 2);
+ exactMatch = false;
+ }
+ return {found: false};
+ }
+
+ layerTileToDataTileCoords(layerTileCoords) {
+ let z = layerTileCoords.z - 2;
+ if (z > this.maxZoom) {
+ let z2 = this.maxZoom,
+ multiplier = 1 << (z - z2);
+ return {
+ x: Math.floor(layerTileCoords.x / multiplier),
+ y: Math.floor(layerTileCoords.y / multiplier),
+ z: z2
+ }
+ } else {
+ return {z, x: layerTileCoords.x, y: layerTileCoords.y}
+ }
+ }
+
+ makeRequestData(dataTileCoords) {
+ let url = wmUtils.makeTileUrl(dataTileCoords);
+ url = urlViaCorsProxy(url);
+ return {
+ url,
+ options: {timeout: 20000}
+ }
+ }
+
+ processResponse(xhr) {
+ const tileData = wmUtils.parseTile(xhr.response, this._project);
+ return {
+ tileData,
+ coords: tileData.coords
+ }
+ }
+
+ calcAdjustment(layerTileCoords, dataTileCoords) {
+ const adjustment = super.calcAdjustment(
+ {x: layerTileCoords.x, y: layerTileCoords.y, z: layerTileCoords.z - 2},
+ dataTileCoords);
+ if (adjustment) {
+ adjustment.offsetX *= 1024;
+ adjustment.offsetY *= 1024;
+ }
+ return adjustment;
+ }
+}
+
+export {WikimapiaLoader};
+\ No newline at end of file
diff --git a/src/lib/leaflet.layer.wikimapia/wikimapia.js b/src/lib/leaflet.layer.wikimapia/wikimapia.js
@@ -1,313 +0,0 @@
-import L from 'leaflet';
-import wmUtils from './wm-utils';
-
-
-function isPointInPolygon(polygon, p) {
- var inside = false;
- var prevNode = polygon[polygon.length - 1],
- node, i;
- for (i = 0; i < polygon.length; i++) {
- node = polygon[i];
- if ((node[0] <= p[0] && p[0] < prevNode[0] || prevNode[0] <= p[0] && p[0] < node[0]) && p[1] < (prevNode[1] - node[1]) * (p[0] - node[0]) / (prevNode[0] - node[0]) + node[1]) {
- inside = !inside;
- }
- prevNode = node;
- }
- return inside;
-}
-
-const Label = L.Class.extend({
- initialize: function(text, latlng) {
- this.text = text;
- this.latlng = latlng;
- },
-
- onAdd: function(map) {
- this._map = map;
- this._container = L.DomUtil.create('div', 'leaflet-marker-icon leaflet-zoom-animated wikimapia-tooltip');
- this._container.innerHTML = this.text;
-
- map._container.appendChild(this._container);
- map.on('viewreset', this._updatePosition, this);
- map.on('mousemove', this.onMouseMove, this);
- this._updatePosition();
- },
-
- onRemove: function(map) {
- map.off('viewreset', this._updatePosition, this);
- map.off('mousemove', this.onMouseMove, this);
- map._container.removeChild(this._container);
- },
-
- onMouseMove: function(e) {
- this.latlng = e.latlng;
- this._updatePosition();
- },
-
- _updatePosition: function() {
- var pos = this._map.latLngToContainerPoint(this.latlng);
- var right = pos.x + this._container.clientWidth + 16 + 2;
- var x, y;
- y = pos.y - 16;
- x = pos.x;
- if (right > this._map._container.clientWidth) {
- x -= this._container.clientWidth + 16 + 2;
- } else {
- x += 16;
- }
- L.Util.extend(this._container.style, {
- top: y + 'px',
- left: x + 'px'
- }
- );
- }
- }
-);
-
-// TODO: как-то посылать remove() в очередь загрузок при событии tileunload
-L.Layer.Wikimapia = L.GridLayer.extend({
- options: {
- tileSize: 512,
- updateWhenIdle: true,
- cacheSize: 30
- },
-
- initialize: function(options) {
- L.GridLayer.prototype.initialize.call(this, options);
- this._cache = {};
- this._cachePriority = [];
- this._downloading = {};
- },
-
- onAdd: function(map) {
- L.GridLayer.prototype.onAdd.call(this, map);
- map.on('mousemove', this.highlightPlace, this);
- // map.on('click', this.showPlaceDetails, this);
- },
-
- onRemove: function(map) {
- map.off('mousemove', this.highlightPlace, this);
- // map.off('click', this.showPlaceDetails, this);
- // if (this.highlightedPlace) {
- // this._map.removeLayer(this.highlightedPlace.polygon);
- // this._map.removeLayer(this.highlightedPlace.label);
- // this.highlightedPlace = null;
- // }
- L.TileLayer.prototype.onRemove.call(this, map);
-
- },
-
- raiseCachePriority: function(tileId) {
- const i = this._cachePriority.indexOf(tileId);
- if (i > -1) {
- this._cachePriority.splice(i, 1);
- }
- this._cachePriority.unshift(tileId);
- },
-
- getWikimapiaDataFromCache: function(tileId) {
- console.log('getWikimapiaDataFromCache', tileId);
- if (tileId in this._cache) {
- console.log('Cache hit', tileId);
- this.raiseCachePriority(tileId);
- return this._cache[tileId];
- }
- while (tileId.length > 1) {
- tileId = tileId.substr(0, tileId.length - 1);
- let tile = this._cache[tileId];
- if (tile && !tile.hasChildren) {
- console.log('Cache hit (parent)', tileId);
- this.raiseCachePriority(tileId);
- return tile;
- }
- }
- console.log('Cache miss', tileId);
- return null;
- },
-
- putWikimapiaDataToCache: function(data) {
- const tileId = data.tileId;
- console.log('putWikimapiaDataToCache', tileId);
- this._cache[tileId] = data;
- this.raiseCachePriority(tileId);
- while (this._cachePriority.length > this.options.cacheSize) {
- let tileId = this._cachePriority.pop();
- delete this._cache[tileId];
- }
- },
-
- // TODO: каждые 50-100 мс отдавать управление
- projectPlacesForZoom: function(tile, viewZoom) {
- if (viewZoom < tile.coords.z) {
- throw new Error('viewZoom < tile.zoom');
- }
- if (tile.places && tile.places[0] && tile.places[0].projectedPolygons &&
- tile.places[0].projectedPolygons[viewZoom]) {
- return;
- }
- const virtualTileSize = 256 * (2 ** (viewZoom - tile.coords.z));
- const p1 = L.point([tile.coords.x * virtualTileSize, tile.coords.y * virtualTileSize]),
- p2 = L.point([(tile.coords.x + 1) * virtualTileSize, (tile.coords.y + 1) * virtualTileSize]),
- latlng1 = this._map.unproject(p1, viewZoom),
- latlng2 = this._map.unproject(p2, viewZoom),
- lat0 = latlng1.lat,
- lng0 = latlng1.lng;
- const qx = (p2.x - p1.x) / (latlng2.lng - latlng1.lng),
- qy = (p2.y - p1.y) / (latlng2.lat - latlng1.lat);
-
- const offsets = [],
- offsetsStep = virtualTileSize / 64;
- const y0 = p1.y;
- for (let y = -virtualTileSize; y <= 2 * virtualTileSize; y += offsetsStep) {
- let lat = y / qy + lat0;
- let offset = this._map.project([lat, lng0], viewZoom).y - y0 - y;
- offsets.push(offset);
- }
-
- let ll, offset, offsetPos, offsetIndex, offsetIndexDelta, x, y;
- const x0 = p1.x;
- for (let place of tile.places) {
- let polygon = place.polygon;
- if (polygon.length < 3) {
- continue;
- }
- let projectedPolygon = [];
- for (let i = 0; i < polygon.length; i++) {
- ll = polygon[i];
- x = (ll[1] - lng0) * qx;
- y = (ll[0] - lat0) * qy;
- offsetPos = (y + virtualTileSize) / offsetsStep;
- offsetIndex = Math.floor(offsetPos);
- offsetIndexDelta = offsetPos - offsetIndex;
- offset = offsets[offsetIndex] * (1 - offsetIndexDelta) + offsets[offsetIndex + 1] * offsetIndexDelta;
- projectedPolygon.push([x + x0, y + offset + y0]);
- }
- projectedPolygon = projectedPolygon.map(L.point);
- projectedPolygon = L.LineUtil.simplify(projectedPolygon, 1.5);
- if (!place.projectedPolygons) {
- place.projectedPolygons = [];
- }
- place.projectedPolygons[viewZoom] = projectedPolygon;
- }
- },
-
- getWikimapiaDataFromServer: async function(tileId) {
- console.log('getWikimapiaDataFromServer', tileId);
- let tile;
-
- try {
- tile = await wmUtils.fetchTile(tileId)
- } catch (e) {
- return {error: e.message};
- } finally {
- delete this._downloading[tileId];
- }
- try {
- tile = wmUtils.parseTile(tile)
- } catch (e) {
- console.log('Error parsing tile', e);
- return {'error': `Malformed wikimapia data for tile ${tileId}`}
- }
-
- this.putWikimapiaDataToCache(tile);
- return tile;
- },
-
- getWikimapiaDataForTile: function(coords) {
- console.log('getWikimapiaDataForTile', coords);
- coords = wmUtils.getWikimapiaTileCoords(coords, this.options.tileSize);
- const tileId = wmUtils.getTileId(coords);
- if (tileId in this._downloading) {
- console.log('Already downloading', coords, tileId);
- return this._downloading[tileId];
- }
- let data = this.getWikimapiaDataFromCache(tileId);
- if (data) {
- return Promise.resolve(data);
- }
- let dataPromise = this.getWikimapiaDataFromServer(tileId);
- this._downloading[tileId] = dataPromise;
- return dataPromise;
- },
-
-
- drawTile: function(coords, canvas, data) {
- if (!this._map) {
- return;
- }
- console.log('drawTile', coords, data);
- if (!data.places) {
- return;
- }
- const canvasCtx = canvas.getContext('2d');
- canvasCtx.strokeStyle = '#CFA600';
- canvasCtx.lineWidth = 1;
- this.projectPlacesForZoom(data, coords.z);
- const x0 = coords.x * this.options.tileSize,
- y0 = coords.y * this.options.tileSize;
- for (let place of data.places) {
- if (!place.projectedPolygons) {
- continue;
- }
- let polygon = place.projectedPolygons[coords.z];
- canvasCtx.moveTo(polygon[0].x - x0, polygon[0].y - y0);
- let p;
- for (let i = 1; i < polygon.length; i++) {
- p = polygon[i];
- canvasCtx.lineTo(p.x - x0, p.y - y0);
- }
- canvasCtx.lineTo(polygon[0].x - x0, polygon[0].y - y0);
- }
- canvasCtx.stroke();
-
- },
-
- createTile: function(coords, done) {
- console.log('createTile', coords);
- const canvas = L.DomUtil.create('canvas', 'leaflet-tile');
- canvas.width = this.options.tileSize;
- canvas.height = this.options.tileSize;
- this.getWikimapiaDataForTile(coords)
- .then((data) => {
- let t1 = Date.now();
- this.drawTile(coords, canvas, data)
- let t2 = Date.now();
- console.log('Tile drawn', t2 - t1);
- }
- )
- .then(() => {
- done(null, canvas)
- }
- );
- return canvas;
- },
-
- getTileAtLayerPoint: function(x, y, z) {
- for (let tileId of this._cachePriority) {
- let tile = this._cache[tileId];
-
- }
- // var i, tile;
-
- // for (i = 0; i < this.tileCache.length; i++) {
- // tile = this.tileCache[i];
- // if (x >= tile.x0 && x < tile.x0 + 1024 && y >= tile.y0 && y < tile.y0 + 1024) {
- // return tile;
- // }
- // }
- },
-
- getPlaceAtLayerPoint: function(x, y, places) {
- var j, bounds, place;
- for (j = places.length - 1; j >= 0; j--) {
- place = places[j];
- bounds = place.localBoundsWESN;
- if (x >= bounds[0] && x <= bounds[1] && y >= bounds[3] && y <= bounds[2] && isPointInPolygon(place.localPolygon, [x, y])) {
- return place;
- }
- }
- }
-
-
- }
-);
diff --git a/src/lib/leaflet.layer.wikimapia/wm-utils.js b/src/lib/leaflet.layer.wikimapia/wm-utils.js
@@ -1,7 +1,3 @@
-import urlViaCorsProxy from 'lib/CORSProxy';
-import 'lib/xhr-promise';
-
-
// (1233,130,5) -> "032203"
function getTileId({x, y, z}) {
let id = [];
@@ -16,6 +12,12 @@ function getTileId({x, y, z}) {
return id.reverse().join('');
}
+function makeTileUrl(coords) {
+ const
+ tileId = getTileId(coords),
+ urlPath = tileId.replace(/(\d{3})(?!$)/g, '$1/'); // "033331022" -> "033/331/022"
+ return `http://wikimapia.org/z1/itiles/${urlPath}.xy?342342`;
+}
function tileIdToCoords(tileId) {
const z = tileId.length - 1;
@@ -46,29 +48,6 @@ function getWikimapiaTileCoords(coords, viewTileSize) {
return {x, y, z};
}
-function fetchTile(tileId) {
- let url = tileId.replace(/(\d{3})(?!$)/g, '$1/'); // "033331022" -> "033/331/022"
- url = 'http://wikimapia.org/z1/itiles/' + url + '.xy?342342';
-
- url = urlViaCorsProxy(url);
- let {promise, requestId} = window.xmlHttpRequestQueue.put(url, {timeout: 30000});
- promise = promise.then((xhr) => {
- if (xhr.status === 0) {
- throw new Error(`Network error while fetching wikimapia data, request "${url}"`);
- }
- if (xhr.status !== 200) {
- throw new Error(`Wikimapia server responded with status ${xhr.status}, request "${url}"`);
- }
- return xhr.response;
- }
- );
- const abort = () => {
- window.xmlHttpRequestQueue.remove(requestId);
- };
- // return {promise, abort};
- return promise;
-
-}
function decodeTitles(s) {
const titles = {};
@@ -120,7 +99,23 @@ function decodePolygon(s) {
return coords;
}
-function parseTile(s) {
+function makeCoordsLocal(line, tileCoords, projectFunc) {
+ const {x: tileX, y: tileY, z: tileZ} = tileCoords,
+ x0 = tileX * 1024,
+ y0 = tileY * 1024,
+ localCoords = [];
+ let latlon, p;
+ for (let i = 0; i < line.length; i++) {
+ latlon = line[i];
+ p = projectFunc(latlon, tileZ + 2);
+ p.x -= x0;
+ p.y -= y0;
+ localCoords.push(p);
+ }
+ return localCoords;
+}
+
+function parseTile(s, projectFunc) {
const tile = {};
const places = tile.places = [];
const lines = s.split('\n');
@@ -170,9 +165,67 @@ function parseTile(s) {
throw new Error(`Polygon has ${coords.length} points`);
}
place.polygon = coords;
+ place.localPolygon = makeCoordsLocal(coords, tile.coords, projectFunc);
+ // place.localBoundsWESN = makeBoundsLocal(place.boundsWESN);
places.push(place);
}
return tile;
}
-export default {getTileId, getWikimapiaTileCoords, fetchTile, parseTile}
-\ No newline at end of file
+// быстрое проектирование полигонов
+// TODO: каждые 50-100 мс отдавать управление
+// projectPlacesForZoom: function(tile, viewZoom) {
+// if (viewZoom < tile.coords.z) {
+// throw new Error('viewZoom < tile.zoom');
+// }
+// if (tile.places && tile.places[0] && tile.places[0].projectedPolygons &&
+// tile.places[0].projectedPolygons[viewZoom]) {
+// return;
+// }
+// const virtualTileSize = 256 * (2 ** (viewZoom - tile.coords.z));
+// const p1 = L.point([tile.coords.x * virtualTileSize, tile.coords.y * virtualTileSize]),
+// p2 = L.point([(tile.coords.x + 1) * virtualTileSize, (tile.coords.y + 1) * virtualTileSize]),
+// latlng1 = this._map.unproject(p1, viewZoom),
+// latlng2 = this._map.unproject(p2, viewZoom),
+// lat0 = latlng1.lat,
+// lng0 = latlng1.lng;
+// const qx = (p2.x - p1.x) / (latlng2.lng - latlng1.lng),
+// qy = (p2.y - p1.y) / (latlng2.lat - latlng1.lat);
+//
+// const offsets = [],
+// offsetsStep = virtualTileSize / 64;
+// const y0 = p1.y;
+// for (let y = -virtualTileSize; y <= 2 * virtualTileSize; y += offsetsStep) {
+// let lat = y / qy + lat0;
+// let offset = this._map.project([lat, lng0], viewZoom).y - y0 - y;
+// offsets.push(offset);
+// }
+//
+// let ll, offset, offsetPos, offsetIndex, offsetIndexDelta, x, y;
+// const x0 = p1.x;
+// for (let place of tile.places) {
+// let polygon = place.polygon;
+// if (polygon.length < 3) {
+// continue;
+// }
+// let projectedPolygon = [];
+// for (let i = 0; i < polygon.length; i++) {
+// ll = polygon[i];
+// x = (ll[1] - lng0) * qx;
+// y = (ll[0] - lat0) * qy;
+// offsetPos = (y + virtualTileSize) / offsetsStep;
+// offsetIndex = Math.floor(offsetPos);
+// offsetIndexDelta = offsetPos - offsetIndex;
+// offset = offsets[offsetIndex] * (1 - offsetIndexDelta) + offsets[offsetIndex + 1] * offsetIndexDelta;
+// projectedPolygon.push([x + x0, y + offset + y0]);
+// }
+// projectedPolygon = projectedPolygon.map(L.point);
+// projectedPolygon = L.LineUtil.simplify(projectedPolygon, 1.5);
+// if (!place.projectedPolygons) {
+// place.projectedPolygons = [];
+// }
+// place.projectedPolygons[viewZoom] = projectedPolygon;
+// }
+// },
+
+export default {getTileId, getWikimapiaTileCoords, parseTile, makeTileUrl}
+\ No newline at end of file
diff --git a/src/lib/tiled-data-loader/index.js b/src/lib/tiled-data-loader/index.js
@@ -41,9 +41,9 @@ class TiledDataLoader {
}
calcAdjustment(layerTileCoords, dataTileCoords) {
- if (layerTileCoords.x == dataTileCoords.x &&
- layerTileCoords.y == dataTileCoords.y &&
- layerTileCoords.z == dataTileCoords.z) {
+ if (layerTileCoords.x === dataTileCoords.x &&
+ layerTileCoords.y === dataTileCoords.y &&
+ layerTileCoords.z === dataTileCoords.z) {
return null;
}
if (dataTileCoords.z > layerTileCoords.z) {