mirror of
https://github.com/bilawalsidhu/gods-eye-view.git
synced 2026-11-04 10:24:02 +00:00
- No pointer cursor over coverage lines (no other layer has one); a click test replaces the hover tests. - No legend: one source, one colour. - The on-globe credit lives in index.js; credits.js is gone. - Billboard glyphs are SVG data URLs with the same geometry, so tests need no canvas stub. - The tile cache keeps the 120 most recently used tiles, same 24 h TTL, instead of a byte budget; listTileLayers was test-only. - providers/mapillary/ is flattened into the layer and its policy merged into one policy.js; the source's method list is a literal in the catalog. - One fakeCesiumViewer for the layer tests. - The fixture gate keeps the steps the unit tests do not cover: coverage and credit, a rejected key, line -> cone -> photo, close, a keyless page. Co-Authored-By: Claude Fable 5.1 <[email protected]>
41 lines
1.4 KiB
JavaScript
41 lines
1.4 KiB
JavaScript
import { PbfReader } from 'pbf';
|
||
import { VectorTile } from '@mapbox/vector-tile';
|
||
import { tileLocalToLonLat } from './tileMath.js';
|
||
|
||
/**
|
||
* Decode a `mly1_public` coverage tile (z11–14) into sequences. The z14
|
||
* `image` layer, which can hold >150k points, is skipped.
|
||
* @param {Uint8Array} bytes
|
||
* @param {{x:number,y:number,z:number}} address
|
||
*/
|
||
export function decodeCoverageTile(bytes, address) {
|
||
const result = { sequences: [] };
|
||
if (!bytes || !bytes.length) return result;
|
||
const tile = new VectorTile(new PbfReader(bytes));
|
||
const { x, y, z } = address;
|
||
const sequenceLayer = tile.layers.sequence;
|
||
if (sequenceLayer) {
|
||
for (let i = 0; i < sequenceLayer.length; i++) {
|
||
const feature = sequenceLayer.feature(i);
|
||
const props = feature.properties || {};
|
||
// A sequence with a capture gap is a multi-line: keep each part as its
|
||
// own line, so no straight segment is drawn across the gap.
|
||
const parts = [];
|
||
for (const line of feature.loadGeometry()) {
|
||
const part = line.map((point) =>
|
||
tileLocalToLonLat(point.x, point.y, sequenceLayer.extent, x, y, z),
|
||
);
|
||
if (part.length >= 2) parts.push(part);
|
||
}
|
||
if (!parts.length) continue;
|
||
result.sequences.push({
|
||
id: String(props.id ?? feature.id ?? `${x}/${y}/${i}`),
|
||
capturedAt: Number(props.captured_at) || 0,
|
||
isPano: props.is_pano === true,
|
||
parts,
|
||
});
|
||
}
|
||
}
|
||
return result;
|
||
}
|