UNPKG

@polar/plugin-draw

Version:

Draw plugin for POLAR that adds draw interactions to the map, allowing users to place various shapes and texts.

107 lines (100 loc) 3.56 kB
import compare from 'just-compare' import { FeatureCollection, Feature as GeoJsonFeature } from 'geojson' import { Feature, Map } from 'ol' import { GeoJSON } from 'ol/format' import { getVectorFeaturesByFeatureRequest, parseWfsResponse, } from '@polar/lib-get-features' import { rawLayerList } from '@masterportal/masterportalapi' import { booleanIntersects } from '@turf/boolean-intersects' import { DrawMetaService } from '@polar/lib-custom-types' import { GeometryType } from '../../types' const reader = new GeoJSON() type Aggregator = ( propertiesArray: Exclude<GeoJsonFeature['properties'], null>[] ) => GeoJsonFeature['properties'][] | GeoJsonFeature['properties'] const aggregators: Record< Required<DrawMetaService>['aggregationMode'], Aggregator > = { all: (x) => x, unequal: (propertiesArray) => propertiesArray.reduce((accumulator, current) => { if (accumulator.every((entry) => !compare(entry, current))) { accumulator.push(current) } return accumulator }, []), } const filterProperties = ( properties: Exclude<GeoJsonFeature['properties'], null>, propertyNames?: string[] ) => propertyNames && propertyNames.length ? Object.fromEntries( Object.entries(properties).filter(([key]) => propertyNames.includes(key) ) ) : properties const aggregateProperties = ( propertiesArray: GeoJsonFeature['properties'][], propertyNames?: string[], mode: DrawMetaService['aggregationMode'] = 'unequal' ) => aggregators[mode]( propertiesArray .filter((properties) => properties !== null) .map((properties) => filterProperties(properties, propertyNames)) ) /** @throws */ export const enrichWithMetaServices = ( featureCollection: FeatureCollection<GeometryType>, map: Map, metaServices: DrawMetaService[], signal: AbortSignal ): Promise<GeoJsonFeature<GeometryType>[]> => Promise.all( featureCollection.features.map(async (feature) => ({ ...feature, properties: { ...feature.properties, metaProperties: { ...(feature.properties?.metaProperties || {}), ...Object.fromEntries( await Promise.all( metaServices.map(({ id, propertyNames, aggregationMode }) => getVectorFeaturesByFeatureRequest({ feature: reader.readFeature( JSON.stringify(feature) ) as unknown as Feature, fetchLayerId: id, projectionCode: map.getView().getProjection().getCode(), signal, }) .then((response) => rawLayerList.getLayerWhere({ id }).typ === 'WFS' ? parseWfsResponse(response, undefined, false) : (response.json() as Promise<FeatureCollection>) ) .then((featuresFromBbox) => { const applicableProperties = featuresFromBbox.features .filter((featureFromBbox) => booleanIntersects(featureFromBbox, feature) ) .map(({ properties }) => properties) const aggregatedProperties = aggregateProperties( applicableProperties, propertyNames, aggregationMode ) return [id, aggregatedProperties] }) ) ) ), }, }, })) )