mirror of
https://github.com/FoggedLens/iD.git
synced 2026-05-19 23:14:47 +02:00
Imagery vintage improvements:
- Cache vintage lookups from Bing API - Actually sample a tile at the center of the viewport, rather than just divinding tiles/2 (not a good guess) - Refactor the start-end range code into one place
This commit is contained in:
@@ -12,6 +12,17 @@ function localeDateString(s) {
|
||||
return d.toLocaleDateString();
|
||||
}
|
||||
|
||||
function vintageRange(vintage) {
|
||||
var s;
|
||||
if (vintage.start || vintage.end) {
|
||||
s = (vintage.start || '?');
|
||||
if (vintage.start !== vintage.end) {
|
||||
s += ' - ' + (vintage.end || '?');
|
||||
}
|
||||
}
|
||||
return s;
|
||||
}
|
||||
|
||||
|
||||
export function rendererBackgroundSource(data) {
|
||||
var source = _.clone(data),
|
||||
@@ -114,11 +125,13 @@ export function rendererBackgroundSource(data) {
|
||||
source.copyrightNotices = function() {};
|
||||
|
||||
|
||||
source.getVintage = function(center, zoom, callback) {
|
||||
callback(null, {
|
||||
source.getVintage = function(center, tileCoord, callback) {
|
||||
var vintage = {
|
||||
start: localeDateString(source.startDate),
|
||||
end: localeDateString(source.endDate)
|
||||
});
|
||||
};
|
||||
vintage.range = vintageRange(vintage);
|
||||
callback(null, vintage);
|
||||
};
|
||||
|
||||
|
||||
@@ -136,6 +149,7 @@ rendererBackgroundSource.Bing = function(data, dispatch) {
|
||||
key = 'Arzdiw4nlOJzRwOz__qailc8NiR31Tt51dN2D7cm57NrnceZnCpgOkmJhNpGoppU', // Same as P2 and JOSM
|
||||
url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial?include=ImageryProviders&key=' +
|
||||
key + '&jsonp={callback}',
|
||||
cache = {},
|
||||
providers = [];
|
||||
|
||||
jsonpRequest(url, function(json) {
|
||||
@@ -168,22 +182,32 @@ rendererBackgroundSource.Bing = function(data, dispatch) {
|
||||
};
|
||||
|
||||
|
||||
bing.getVintage = function(center, zoom, callback) {
|
||||
zoom = Math.min(zoom, 21);
|
||||
|
||||
var centerPoint = center[1] + ',' + center[0],
|
||||
bing.getVintage = function(center, tileCoord, callback) {
|
||||
var tileId = tileCoord.slice(0, 3).join('/'),
|
||||
zoom = Math.min(tileCoord[2], 21),
|
||||
centerPoint = center[1] + ',' + center[0], // lat,lng
|
||||
url = 'https://dev.virtualearth.net/REST/v1/Imagery/Metadata/Aerial/' + centerPoint +
|
||||
'?zl=' + zoom + '&key=' + key + '&jsonp={callback}';
|
||||
|
||||
if (!cache[tileId]) {
|
||||
cache[tileId] = {};
|
||||
}
|
||||
if (cache[tileId] && cache[tileId].vintage) {
|
||||
return callback(null, cache[tileId].vintage);
|
||||
}
|
||||
|
||||
jsonpRequest(url, function(result) {
|
||||
var err = (!result && 'Unknown Error') || result.errorDetails;
|
||||
if (err) {
|
||||
return callback(err);
|
||||
} else {
|
||||
return callback(null, {
|
||||
var vintage = {
|
||||
start: localeDateString(result.resourceSets[0].resources[0].vintageStart),
|
||||
end: localeDateString(result.resourceSets[0].resources[0].vintageEnd)
|
||||
});
|
||||
};
|
||||
vintage.range = vintageRange(vintage);
|
||||
cache[tileId].vintage = vintage;
|
||||
return callback(null, vintage);
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import * as d3 from 'd3';
|
||||
import { t } from '../util/locale';
|
||||
import { d3geoTile } from '../lib/d3.geo.tile';
|
||||
import { utilPrefixCSSProperty } from '../util/index';
|
||||
import { geoEuclideanDistance } from '../geo';
|
||||
import { utilPrefixCSSProperty } from '../util';
|
||||
import { rendererBackgroundSource } from './background_source.js';
|
||||
|
||||
|
||||
@@ -98,7 +99,7 @@ export function rendererTileLayer(context) {
|
||||
tile().forEach(function(d) {
|
||||
addSource(d);
|
||||
if (d[3] === '') return;
|
||||
if (typeof d[3] !== 'string') return; // Workaround for chrome crash https://github.com/openstreetmap/iD/issues/2295
|
||||
if (typeof d[3] !== 'string') return; // Workaround for #2295
|
||||
requests.push(d);
|
||||
if (cache[d[3]] === false && lookUp(d)) {
|
||||
requests.push(addSource(lookUp(d)));
|
||||
@@ -119,6 +120,7 @@ export function rendererTileLayer(context) {
|
||||
source.offset()[1] * Math.pow(2, z)
|
||||
];
|
||||
|
||||
|
||||
function load(d) {
|
||||
cache[d[3]] = true;
|
||||
d3.select(this)
|
||||
@@ -146,9 +148,11 @@ export function rendererTileLayer(context) {
|
||||
'scale(' + scale + ',' + scale + ')';
|
||||
}
|
||||
|
||||
function debugCoordinates(d) {
|
||||
function tileCenter(d) {
|
||||
var _ts = tileSize * Math.pow(2, z - d[2]);
|
||||
var scale = tileSizeAtZoom(d, z);
|
||||
// FIXME: this scale * tileSize/number stuff is hacky, and more for displaying the debug text.
|
||||
// It's not really the center of the tile, but it is guaranteed to be somewhere in the tile.
|
||||
return [
|
||||
((d[0] * _ts) - tileOrigin[0] + pixelOffset[0] + scale * (tileSize / 4)),
|
||||
((d[1] * _ts) - tileOrigin[1] + pixelOffset[1] + scale * (tileSize / 2))
|
||||
@@ -156,16 +160,35 @@ export function rendererTileLayer(context) {
|
||||
}
|
||||
|
||||
function debugTransform(d) {
|
||||
var coord = debugCoordinates(d);
|
||||
var coord = tileCenter(d);
|
||||
return 'translate(' + coord[0] + 'px,' + coord[1] + 'px)';
|
||||
}
|
||||
|
||||
|
||||
// Pick a representative tile near the center of the viewport
|
||||
// (This is useful for sampling the imagery vintage)
|
||||
var dims = tile.size(),
|
||||
mapCenter = [dims[0] / 2, dims[1] / 2],
|
||||
minDist = Math.max(dims[0], dims[1]),
|
||||
nearCenter;
|
||||
|
||||
requests.forEach(function(d) {
|
||||
var c = tileCenter(d);
|
||||
var dist = geoEuclideanDistance(c, mapCenter);
|
||||
if (dist < minDist) {
|
||||
minDist = dist;
|
||||
nearCenter = d;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
var image = selection.selectAll('img')
|
||||
.data(requests, function(d) { return d[3]; });
|
||||
|
||||
image.exit()
|
||||
.style(transformProp, imageTransform)
|
||||
.classed('tile-removing', true)
|
||||
.classed('tile-center', false)
|
||||
.each(function() {
|
||||
var tile = d3.select(this);
|
||||
window.setTimeout(function() {
|
||||
@@ -184,7 +207,9 @@ export function rendererTileLayer(context) {
|
||||
.merge(image)
|
||||
.style(transformProp, imageTransform)
|
||||
.classed('tile-debug', showDebug)
|
||||
.classed('tile-removing', false);
|
||||
.classed('tile-removing', false)
|
||||
.classed('tile-center', function(d) { return d === nearCenter; });
|
||||
|
||||
|
||||
|
||||
var debug = selection.selectAll('.tile-label-debug')
|
||||
@@ -219,20 +244,11 @@ export function rendererTileLayer(context) {
|
||||
.selectAll('.tile-label-debug-vintage')
|
||||
.each(function(d) {
|
||||
var span = d3.select(this);
|
||||
var center = context.projection.invert(debugCoordinates(d));
|
||||
source.getVintage(center, d[2], function(err, result) {
|
||||
var vintage = '';
|
||||
if (result) {
|
||||
if (result.start || result.end) {
|
||||
vintage = (result.start || '?');
|
||||
if (result.start !== result.end) {
|
||||
vintage += ' - ' + (result.end || '?');
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
span
|
||||
.text(vintage || t('infobox.imagery.vintage') + ': ' + t('infobox.imagery.unknown'));
|
||||
var center = context.projection.invert(tileCenter(d));
|
||||
source.getVintage(center, d, function(err, result) {
|
||||
span.text((result && result.range) ||
|
||||
t('infobox.imagery.vintage') + ': ' + t('infobox.imagery.unknown')
|
||||
);
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
@@ -64,31 +64,20 @@ export function uiPanelImagery(context) {
|
||||
|
||||
var debouncedGetVintage = _.debounce(getVintage, 250);
|
||||
function getVintage(selection) {
|
||||
var tile = d3.select('.layer-background img');
|
||||
var tile = d3.select('.layer-background img.tile-center'); // tile near viewport center
|
||||
if (tile.empty()) return;
|
||||
|
||||
var tiledata = tile.datum(),
|
||||
zoom = tiledata[2] || Math.floor(context.map().zoom()),
|
||||
var d = tile.datum(),
|
||||
zoom = (d && d.length >= 3 && d[2]) || Math.floor(context.map().zoom()),
|
||||
center = context.map().center();
|
||||
|
||||
currZoom = String(zoom);
|
||||
selection.selectAll('.zoom')
|
||||
.text(currZoom);
|
||||
|
||||
background.baseLayerSource().getVintage(center, currZoom, function(err, result) {
|
||||
if (!result) {
|
||||
currVintage = t('infobox.imagery.unknown');
|
||||
} else {
|
||||
if (result.start || result.end) {
|
||||
currVintage = (result.start || '?');
|
||||
if (result.start !== result.end) {
|
||||
currVintage += ' - ' + (result.end || '?');
|
||||
}
|
||||
} else {
|
||||
currVintage = t('infobox.imagery.unknown');
|
||||
}
|
||||
}
|
||||
|
||||
if (!d || !d.length >= 3) return;
|
||||
background.baseLayerSource().getVintage(center, d, function(err, result) {
|
||||
currVintage = (result && result.range) || t('infobox.imagery.unknown');
|
||||
selection.selectAll('.vintage')
|
||||
.text(currVintage);
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user