Skip to content

Commit 23a5ef0

Browse files
committed
feat(landing): use attribution polygon for layer intersections if we have them
1 parent 4bc33ff commit 23a5ef0

File tree

4 files changed

+59
-28
lines changed

4 files changed

+59
-28
lines changed

packages/landing/src/attribution.ts

Lines changed: 16 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,24 @@ export class MapAttributionState {
1717
/** Rendering process needs synch access */
1818
_attrsSync: Map<string, Attribution> = new Map();
1919

20+
getAttribution(layerKey: string, loadUrl: string): Promise<Attribution | null> {
21+
const attrs = this._attrs.get(layerKey);
22+
if (attrs) return attrs;
23+
const attrLoad = Attribution.load(loadUrl)
24+
.then((a) => {
25+
if (a == null) return null;
26+
a.isIgnored = this.isIgnored;
27+
this._attrsSync.set(layerKey, a);
28+
return a;
29+
})
30+
.catch(() => null);
31+
this._attrs.set(layerKey, attrLoad);
32+
return attrLoad;
33+
}
34+
2035
/** Load a attribution from a url, return a cached copy if we have one */
2136
getCurrentAttribution(): Promise<Attribution | null> {
22-
const cacheKey = Config.map.layerKeyTms;
23-
let attrs = this._attrs.get(cacheKey);
24-
if (attrs == null) {
25-
attrs = Attribution.load(Config.map.toTileUrl(MapOptionType.Attribution)).catch(() => null);
26-
this._attrs.set(cacheKey, attrs);
27-
void attrs.then((a) => {
28-
if (a == null) return;
29-
a.isIgnored = this.isIgnored;
30-
this._attrsSync.set(Config.map.layerKeyTms, a);
31-
});
32-
}
33-
return attrs;
37+
return this.getAttribution(Config.map.layerKeyTms, Config.map.toTileUrl(MapOptionType.Attribution));
3438
}
3539

3640
/** Filter the attribution to the map bounding box */

packages/landing/src/components/layer.switcher.dropdown.tsx

Lines changed: 26 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,12 @@
11
import { Bounds, GoogleTms, Projection } from '@basemaps/geo';
2+
import { Wgs84 } from '@linzjs/geojson';
23
import { ChangeEventHandler, Component, ReactNode } from 'react';
34
import Select from 'react-select';
45

6+
import { MapAttrState } from '../attribution.js';
57
import { Config, GaEvent, gaEvent } from '../config.js';
68
import { LayerInfo, MapConfig } from '../config.map.js';
9+
import { MapOptionType } from '../url.js';
710

811
type CategoryMap = Map<string, { label: string; options: { label: string; value: string }[] }>;
912

@@ -48,7 +51,12 @@ export class LayerSwitcherDropdown extends Component<unknown, LayerSwitcherDropd
4851
}
4952

5053
override componentDidMount(): void {
51-
this.setState({ zoomToExtent: true, currentLayer: Config.map.layerKey });
54+
this.setState({ zoomToExtent: false, currentLayer: Config.map.layerKey, filterToExtent: true });
55+
// Trigger a map load
56+
void MapAttrState.getAttribution(
57+
'all',
58+
Config.map.toTileUrl(MapOptionType.Attribution, GoogleTms, 'all', undefined),
59+
).then(() => this.forceUpdate());
5260

5361
void Config.map.layers.then((layers) => {
5462
this.setState({ layers });
@@ -194,22 +202,35 @@ export class LayerSwitcherDropdown extends Component<unknown, LayerSwitcherDropd
194202

195203
let current: Option | null = null;
196204

205+
const allLayers = MapAttrState._attrsSync.get('all');
206+
197207
for (const layer of this.state.layers.values()) {
198208
if (ignoredLayers.has(layer.id)) continue;
199209
if (!layer.projections.has(Config.map.tileMatrix.projection.code)) continue;
200210
total++;
201211
// Always show the current layer
202212
if (layer.id !== currentLayer) {
203213
// Limit all other layers to the extent if requested
204-
if (filterToExtent && !doesLayerIntersect(bounds, layer)) {
205-
hidden++;
206-
continue;
214+
if (filterToExtent) {
215+
if (!doesLayerIntersect(bounds, layer)) {
216+
hidden++;
217+
continue;
218+
}
219+
if (allLayers) {
220+
const currentLayer = allLayers.attributions.filter((f) => f.collection.title === layer.title);
221+
const latLng = Projection.get(GoogleTms).boundsToWgs84BoundingBox(bounds);
222+
// console.log(latLng, Wgs84.bboxToMultiPolygon(latLng));
223+
if (currentLayer.length === 1 && !currentLayer[0].intersection(Wgs84.bboxToMultiPolygon(latLng))) {
224+
hidden++;
225+
continue;
226+
}
227+
}
207228
}
208229
}
209230

210231
const layerId = layer.category ?? 'Unknown';
211232
const layerCategory = categories.get(layerId) ?? { label: layerId, options: [] };
212-
const opt = { value: layer.id, label: layer.name.replace(` ${layer.category}`, '') };
233+
const opt = { value: layer.id, label: layer.title.replace(` ${layer.category}`, '') };
213234
layerCategory.options.push(opt);
214235
categories.set(layerId, layerCategory);
215236
if (layer.id === currentLayer) current = opt;

packages/landing/src/components/layout.header.tsx

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -22,7 +22,7 @@ export class Header extends Component<unknown, HeaderState> {
2222
}
2323

2424
override componentDidMount(): void {
25-
this.setState({ isMenuOpen: false });
25+
this.setState({ isMenuOpen: true });
2626
this._events.push(Config.map.on('change', () => this.forceUpdate()));
2727
this._events.push(Config.map.on('filter', () => this.renderLinksTiles()));
2828

packages/landing/src/config.map.ts

Lines changed: 16 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -275,10 +275,16 @@ export class MapConfig extends Emitter<MapConfigEvents> {
275275
}
276276

277277
export interface LayerInfo {
278-
/** Layer id to use when fetching tiles */
278+
/**
279+
* URL friendly Layer id to use when fetching tiles
280+
* @example "scanned-aerial-imagery-post-1989-12-31"
281+
*/
279282
id: string;
280-
/** Layer name */
281-
name: string;
283+
/**
284+
* Human friendly name of the layer,
285+
* @example "Scanned Aerial Imagery post 31 December 1989"
286+
*/
287+
title: string;
282288
/** Layer category */
283289
category?: string;
284290
/* Bounding box */
@@ -331,15 +337,15 @@ async function loadAllLayers(): Promise<Map<string, LayerInfo>> {
331337
if (upperLeft == null || lowerRight == null || upperLeft.length !== 2) continue;
332338
allLayers.push({
333339
id,
334-
name: title.replace('aerial ', ''),
340+
title: title.replace('aerial ', ''),
335341
upperLeft,
336342
lowerRight,
337343
projections,
338344
category,
339345
} as LayerInfo);
340346
}
341347

342-
allLayers.sort((a, b) => a.name.localeCompare(b.name));
348+
allLayers.sort((a, b) => a.title.localeCompare(b.title));
343349
addDefaultLayers(output);
344350
for (const l of allLayers) output.set(l.id, l);
345351
return output;
@@ -355,21 +361,21 @@ function addDefaultLayers(output: Map<string, LayerInfo>): void {
355361
const layers: LayerInfo[] = [
356362
{
357363
id: 'aerial',
358-
name: 'Aerial Imagery',
364+
title: 'Aerial Imagery',
359365
projections: new Set([EpsgCode.Nztm2000, EpsgCode.Google]),
360366
category: 'Basemaps',
361367
},
362368

363369
{
364370
id: 'topographic::topographic',
365-
name: 'Topographic',
371+
title: 'Topographic',
366372
projections: new Set([EpsgCode.Google]),
367373
category: 'Basemaps',
368374
},
369375

370376
{
371377
id: 'elevation',
372-
name: 'Elevation',
378+
title: 'Elevation',
373379
projections: new Set([EpsgCode.Google]),
374380
category: 'Basemaps',
375381
pipeline: 'terrain-rgb',
@@ -378,14 +384,14 @@ function addDefaultLayers(output: Map<string, LayerInfo>): void {
378384

379385
{
380386
id: 'scanned-aerial-imagery-pre-1990-01-01',
381-
name: 'Scanned Aerial Imagery pre 1 January 1990',
387+
title: 'Scanned Aerial Imagery pre 1 January 1990',
382388
projections: new Set([EpsgCode.Nztm2000, EpsgCode.Google]),
383389
category: 'Scanned Aerial Imagery Basemaps',
384390
},
385391

386392
{
387393
id: 'scanned-aerial-imagery-post-1989-12-31',
388-
name: 'Scanned Aerial Imagery post 31 December 1989',
394+
title: 'Scanned Aerial Imagery post 31 December 1989',
389395
projections: new Set([EpsgCode.Nztm2000, EpsgCode.Google]),
390396
category: 'Scanned Aerial Imagery Basemaps',
391397
},

0 commit comments

Comments
 (0)