Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
4 changes: 4 additions & 0 deletions data/core.yaml
Original file line number Diff line number Diff line change
Expand Up @@ -837,6 +837,10 @@ en:
contrast: Contrast
saturation: Saturation
sharpness: Sharpness
EsriWayback:
name: Esri Wayback
description: Esri Wayback contains archived snapshots of Esri World Imagery created over time.
date: Date
minimap:
description: Show Minimap
tooltip: Show a zoomed out map to help locate the area currently displayed.
Expand Down
1,516 changes: 1,516 additions & 0 deletions data/imagery_esri_wayback.json

Large diffs are not rendered by default.

1 change: 1 addition & 0 deletions modules/core/file_fetcher.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,6 +18,7 @@ export function coreFileFetcher() {
let _fileMap = {
'address_formats': 'data/address_formats.min.json',
'imagery': 'data/imagery.min.json',
'imagery_esri_wayback': 'data/imagery_esri_wayback.min.json',
'intro_graph': 'data/intro_graph.min.json',
'keepRight': 'data/keepRight.min.json',
'languages': 'data/languages.min.json',
Expand Down
49 changes: 41 additions & 8 deletions modules/renderer/background.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,11 @@ import { prefs } from '../core/preferences';
import { fileFetcher } from '../core/file_fetcher';
import { geoMetersToOffset, geoOffsetToMeters, geoExtent } from '../geo';
import { rendererBackgroundSource } from './background_source';
import {
parseWaybackId,
createWaybackSource,
ESRI_WAYBACK_ID
} from './background_source_wayback.js';
import { rendererTileLayer } from './tile_layer';
import { utilQsString, utilStringQs } from '../util';
import { utilRebind } from '../util/rebind';
Expand Down Expand Up @@ -74,6 +79,14 @@ export function rendererBackground(context) {
}
});

// Only add EsriWayback if 'EsriWorldImagery' exists, inserting it right after it
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The "only add if" is not the goal here but given we should always be present, I did not think we need an else-branch here.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I guess one could argue that if one uses a customized instance of iD with it own set of custom imagery sources (that does not include ESRI World Imagery), it does indeed make sense to not insert the "ESRI Wayback" layer.

Maybe it would be slightly more elegant to define "ESRI Wayback" in data/manual_imagery.json somehow (which can be more easily customized by potential forks of iD) instead of hardcoding it here and relying on the presence of another (technically independent) layer. Instead, here we could just make sure that it is sorted properly next to the other ESRI layer. Feel free to leave it as is, though, if you think it is not worth the effort.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

PS: I think it would make more sense to include the Wayback entry after the regular ESRI World Imagery layer: It is more common to use the latest imagery while mapping compared to older versions of the imagery.

const esriWorldImageryIndex = _imageryIndex.backgrounds.findIndex(s => s.id === 'EsriWorldImagery');
if (esriWorldImageryIndex >= 0) {
const esriWorldImagerySource = _imageryIndex.backgrounds[esriWorldImageryIndex];
const waybackSource = createWaybackSource(esriWorldImagerySource, context, dispatch);
_imageryIndex.backgrounds.splice(esriWorldImageryIndex + 1, 0, waybackSource);
}

// Add 'None'
_imageryIndex.backgrounds.unshift(rendererBackgroundSource.None());

Expand Down Expand Up @@ -202,9 +215,13 @@ export function rendererBackground(context) {
const y = +meters[1].toFixed(2);
let hash = utilStringQs(window.location.hash);

/** @type {string|null} */
let id = currSource.id;
if (id === 'custom') {
id = `custom:${currSource.template()}`;
} else if (id === ESRI_WAYBACK_ID) {
// Wayback sources include the date in their key (e.g., 'EsriWayback_2024-01-01')
id = currSource.key();
}

if (id) {
Expand Down Expand Up @@ -477,21 +494,37 @@ export function rendererBackground(context) {
});
}

// Helper function to get fallback background source
function getFallbackSource(preferredSource) {
return preferredSource ||
best ||
(isLastUsedValid && background.findSource(lastUsedBackground)) ||
background.findSource('Bing') ||
first ||
background.findSource('none');
}

// Decide which background layer to display
if (requestedBackground && requestedBackground.indexOf('custom:') === 0) {
const template = requestedBackground.replace(/^custom:/, '');
const custom = background.findSource('custom');
background.baseLayerSource(custom.template(template));
prefs('background-custom-template', template);
} else if (requestedBackground) {
const waybackInfo = parseWaybackId(requestedBackground);
if (waybackInfo.isWayback) {
const waybackSource = background.findSource(ESRI_WAYBACK_ID);
if (waybackSource) {
waybackSource.date(waybackInfo.date);
background.baseLayerSource(waybackSource);
} else {
background.baseLayerSource(getFallbackSource(background.findSource(requestedBackground)));
}
} else {
background.baseLayerSource(getFallbackSource(background.findSource(requestedBackground)));
}
Comment on lines +514 to +525
Copy link
Collaborator Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Reading again, this can likely be…

Suggested change
const waybackInfo = parseWaybackId(requestedBackground);
if (waybackInfo.isWayback) {
const waybackSource = background.findSource(ESRI_WAYBACK_ID);
if (waybackSource) {
waybackSource.date(waybackInfo.date);
background.baseLayerSource(waybackSource);
} else {
background.baseLayerSource(getFallbackSource(background.findSource(requestedBackground)));
}
} else {
background.baseLayerSource(getFallbackSource(background.findSource(requestedBackground)));
}
const waybackInfo = parseWaybackId(requestedBackground);
const waybackSource = background.findSource(ESRI_WAYBACK_ID);
if (waybackInfo.isWayback && waybackSource) {
waybackSource.date(waybackInfo.date);
background.baseLayerSource(waybackSource);
} else {
background.baseLayerSource(getFallbackSource(background.findSource(requestedBackground)));
}

FYI: parseWaybackId validates the URL param to be valid, especially the date given that it is essential for the service.

Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Sounds good to me to simplify those two branches.

} else {
background.baseLayerSource(
background.findSource(requestedBackground) ||
best ||
isLastUsedValid && background.findSource(lastUsedBackground) ||
background.findSource('Bing') ||
first ||
background.findSource('none')
);
background.baseLayerSource(getFallbackSource());
}

const locator = imageryIndex.backgrounds.find(d => d.overlay && d.default);
Expand Down
25 changes: 25 additions & 0 deletions modules/renderer/background_source.js
Original file line number Diff line number Diff line change
Expand Up @@ -395,6 +395,31 @@ rendererBackgroundSource.Bing = function(data, dispatch) {



/**
* @typedef {Object} EsriSource
* @property {string} id
* @property {number} tileSize
* @property {[number, number]} zoomExtent
* @property {boolean} overzoom
* @property {string|null|undefined} [startDate]
* @property {string|null|undefined} [endDate]
* @property {function(): string} name
* @property {function(): any} label
* @property {function(): any} description
* @property {function(): boolean} hasDescription
* @property {function(string|null|undefined): string|EsriSource} template
* @property {function([number, number, number]): string} url
* @property {function(): string} key
* @property {function(): string|null} imageryUsed
* @property {function([number, number], number[], function): void} getMetadata
* @property {function([number, number]): void} fetchTilemap
*/

/**
* Create an Esri imagery source with dynamic zoom detection
* @param {Object} data - Source data object
* @returns {EsriSource} Esri source
*/
rendererBackgroundSource.Esri = function(data) {
// in addition to using the tilemap at zoom level 20, overzoom real tiles - #4327 (deprecated technique, but it works)
if (data.template.match(/blankTile/) === null) {
Expand Down
Loading