UNPKG

@giro3d/giro3d

Version:

A JS/WebGL framework for 3D geospatial data visualization

105 lines (91 loc) 3.88 kB
/* * Copyright (c) 2015-2018, IGN France. * Copyright (c) 2018-2026, Giro3D team. * SPDX-License-Identifier: MIT */ import type ElevationSample from './ElevationSample'; import type GetElevationOptions from './GetElevationOptions'; import type GetElevationResult from './GetElevationResult'; /** * Represents an object that can provide elevations at given coordinates. * * Note: to combine multiple providers into one, you can use the {@link aggregateElevationProviders} function. */ export interface ElevationProvider { /** * Returns the elevation at the specified coordinates, without any coordinate conversion. * @param x - The X coordinate of the location to sample, in the same coordinate system as this elevation provider. * @param y - The Y coordinate of the location to sample, in the same coordinate system as this elevation provider. */ getElevationFast(x: number, y: number): ElevationSample | undefined; /** * Sample the elevation at the specified coordinate. * * Note: sampling might return more than one sample for any given coordinate. You can sort them * by {@link core.ElevationSample.resolution | resolution} to select the best sample for your needs. * @param options - The options. * @param result - The result object to populate with the samples. If none is provided, a new * empty result is created. The existing samples in the array are not removed. Useful to * cumulate samples across different providers. * @returns The {@link GetElevationResult} containing the updated sample array. */ getElevation(options: GetElevationOptions, result?: GetElevationResult): GetElevationResult; } /** @internal */ class AggregateProvider implements ElevationProvider { private readonly _providers: Readonly<ElevationProvider[]>; public constructor(providers: Readonly<ElevationProvider[]>) { this._providers = providers; } public getElevationFast(x: number, y: number): ElevationSample | undefined { const samples: ElevationSample[] = []; // Accumulate elevation samples from all providers. for (let i = 0; i < this._providers.length; i++) { const provider = this._providers[i]; const sample = provider.getElevationFast(x, y); if (sample) { samples.push(sample); } } if (samples.length > 0) { samples.sort((a, b) => a.resolution - b.resolution); return samples[0]; } return undefined; } public getElevation( options: GetElevationOptions, result?: GetElevationResult, ): GetElevationResult { result = result ?? { coordinates: options.coordinates, samples: [], }; // Accumulate elevation samples from all providers. for (let i = 0; i < this._providers.length; i++) { const provider = this._providers[i]; provider.getElevation(options, result); } return result; } } /** * Returns an {@link ElevationProvider} that aggregates multiple providers into one. * The {@link ElevationProvider.getElevation | getElevation} method will then sample * all underlying providers and return a single {@link GetElevationResult} containing * samples from all providers. * * This can be useful if a scene contains multiple overlapping terrains for example. * * @param providers - The providers to aggregate. */ export function aggregateElevationProviders(...providers: ElevationProvider[]): ElevationProvider { if (providers == null || providers.length === 0) { throw new Error('expected at least one provider'); } if (providers.length === 1) { return providers[0]; } return new AggregateProvider(providers); } export default ElevationProvider;