// Offline orthoimagery contact sheet with the original footprint outlines, no invented infill. import { readFileSync, writeFileSync, mkdirSync, existsSync } from 'node:fs' import { resolve } from 'node:path' import { PNG } from 'pngjs' import jpeg from 'jpeg-js' const dir = process.env.GIS_DIR || 'D:/GIS/GIS' const data = JSON.parse(readFileSync(dir + '/planet_110.059,28.258_110.744,28.625-shp/shpOutput/buildings.json')) const out = resolve('.scratch/cockpit-shell-panel-layout/verify/artifacts/t35/imagery') mkdirSync(out, { recursive: true }) const px = (lon, lat, z) => [ ((lon + 180) / 360) * 2 ** z * 256, ((1 - Math.asinh(Math.tan((lat * Math.PI) / 180)) / Math.PI) / 2) * 2 ** z * 256, ] const sets = [ ['south', 110.401, 28.428, 18], ['north', 110.395, 28.454, 18], ] for (const [name, lon, lat, z] of sets) { const center = px(lon, lat, z) const x0 = Math.floor(center[0] / 256) - 3, y0 = Math.floor(center[1] / 256) - 3 const img = new PNG({ width: 1792, height: 1792 }) img.data.fill(255) let tiles = 0 for (let y = 0; y < 7; y++) for (let x = 0; x < 7; x++) { const file = dir + `/yuanlingPic3/${z}/${x0 + x}/${2 ** z - 1 - (y0 + y)}.png` if (!existsSync(file)) continue const bytes = readFileSync(file) const t = bytes[0] === 0xff ? jpeg.decode(bytes) : PNG.sync.read(bytes) PNG.bitblt(t, img, 0, 0, 256, 256, x * 256, y * 256) tiles++ } writeFileSync(resolve(out, name + '-satellite.png'), PNG.sync.write(img)) function line(a, b) { let steps = Math.ceil(Math.hypot(b[0] - a[0], b[1] - a[1])) for (let i = 0; i <= steps; i++) { let x = Math.round(a[0] + ((b[0] - a[0]) * i) / steps), y = Math.round(a[1] + ((b[1] - a[1]) * i) / steps) if (x < 0 || y < 0 || x >= img.width || y >= img.height) continue const k = (y * img.width + x) * 4 img.data[k] = 255 img.data[k + 1] = 208 img.data[k + 2] = 0 } } const inside = [] for (const f of data.features) { let rings = f.geometry.type === 'Polygon' ? [f.geometry.coordinates[0]] : f.geometry.coordinates.map((p) => p[0]) for (const r of rings) { let p = r.map((c) => { let a = px(...c, z) return [a[0] - x0 * 256, a[1] - y0 * 256] }) if (p.every((c) => c[0] >= 0 && c[1] >= 0 && c[0] < img.width && c[1] < img.height)) { inside.push({ id: String(f.properties.osm_id), ring: r, px: p }) for (let i = 1; i < p.length; i++) line(p[i - 1], p[i]) } } } writeFileSync(resolve(out, name + '-footprints.png'), PNG.sync.write(img)) writeFileSync( resolve(out, name + '-source.json'), JSON.stringify({ z, x0, y0, width: 1792, features: inside }, null, 2) ) console.log({ name, tiles, footprints: inside.length, out }) }