import { Injectable } from '@angular/core'; import { BodyRecord } from '../../shared/models/body.model'; import { DeepSkyRecord } from '../../shared/models/deepsky.model'; import { ExoplanetRecord } from '../../shared/models/exoplanet.model'; import { decodeStarCatalog, StarCatalogIndex } from '../../shared/models/star-catalog'; import { StarRecord } from '../../shared/models/star.model'; export interface StarField { stars: StarRecord[]; /** Positions in parsecs, in the same order as `stars`, packed as [x0,y0,z0,x1,y1,z1,...]. */ positions: Float32Array; } /** * Loads the ETL-generated static assets (`src/assets/data/*`, served at `/assets/data/*`). * Each dataset is fetched at most once per app session and cached in memory. */ @Injectable({ providedIn: 'root' }) export class DataLoaderService { private starFieldPromise?: Promise; private bodiesPromise?: Promise; private exoplanetsPromise?: Promise; private deepSkyPromise?: Promise; loadStars(): Promise { this.starFieldPromise ??= this.fetchStars(); return this.starFieldPromise; } loadBodies(): Promise { this.bodiesPromise ??= this.fetchJson('assets/data/bodies.json'); return this.bodiesPromise; } loadExoplanets(): Promise { this.exoplanetsPromise ??= this.fetchJson('assets/data/exoplanets.json'); return this.exoplanetsPromise; } loadDeepSky(): Promise { this.deepSkyPromise ??= this.fetchJson('assets/data/deepsky.json'); return this.deepSkyPromise; } /** * Three assets rather than one, fetched in parallel: the strings as JSON, and the numbers as * two binary column stores. See `star-catalog.ts` for why the catalogue is not a single array * of JSON objects. */ private async fetchStars(): Promise { const [index, positionBuffer, metaBuffer] = await Promise.all([ fetch('assets/data/stars-index.json').then((response) => response.json() as Promise), fetch('assets/data/stars.bin').then((response) => response.arrayBuffer()), fetch('assets/data/stars-meta.bin').then((response) => response.arrayBuffer()) ]); const positions = new Float32Array(positionBuffer); return { stars: decodeStarCatalog(index, positions, metaBuffer), positions }; } private fetchJson(url: string): Promise { return fetch(url).then((response) => response.json() as Promise); } }