UNPKG

@giro3d/giro3d

Version:

A JS/WebGL framework for 3D geospatial data visualization

103 lines (77 loc) 2.93 kB
/* * Copyright (c) 2015-2018, IGN France. * Copyright (c) 2018-2026, Giro3D team. * SPDX-License-Identifier: MIT */ import type { Feature } from 'ol'; import type { Extent as OLExtent } from 'ol/extent'; import type { Geometry } from 'ol/geom'; import type CoordinateSystem from '../../core/geographic/CoordinateSystem'; import type Extent from '../../core/geographic/Extent'; import OpenLayersUtils from '../../utils/OpenLayersUtils'; import PromiseUtils from '../../utils/PromiseUtils'; export async function processFeatures( features: Feature<Geometry>[], sourceProjection: CoordinateSystem, targetProjection: CoordinateSystem, optionalProcessings?: { getFeatureId?: (feature: Feature) => number | string; transformer?: (feature: Feature, geometry: Geometry) => void; }, ): Promise<Feature<Geometry>[]> { // Since everything happens in the main frame, we split the computation // into several slices that are executed over time. await PromiseUtils.nextFrame(); const shouldReproject = sourceProjection.id !== targetProjection.id; const tmpExtent = [0, 0, 0, 0]; const transformer = (feature: Feature, index: number): Feature | null => { const id = optionalProcessings?.getFeatureId != null ? optionalProcessings.getFeatureId(feature) : index; feature.setId(id); const geometry = feature.getGeometry(); // We ignore features without geometry as they cannot be represented. if (geometry) { if (shouldReproject) { // Reproject geometry geometry.transform(sourceProjection.id, targetProjection.id); } // Pre-compute extent to speedup ulterior computations geometry.getExtent(tmpExtent); if (optionalProcessings?.transformer) { optionalProcessings.transformer(feature, geometry); } return feature; } return null; }; // Process the features in batched slices const actualFeatures = await PromiseUtils.batch(features, transformer); return actualFeatures; } export function intersects(feature: Feature, olExtent: OLExtent): boolean { const geom = feature.getGeometry(); if (!geom) { return false; } if (geom.intersectsExtent(olExtent)) { return true; } return false; } export async function filterByExtent( features: Feature[], extent: Extent, options?: { signal?: AbortSignal }, ): Promise<Feature[]> { const olExtent = OpenLayersUtils.toOLExtent(extent); const filter = (feature: Feature): Feature | null => { if (intersects(feature, olExtent)) { return feature; } return null; }; const filtered = await PromiseUtils.batch(features, filter, { signal: options?.signal }); return filtered; }