/** * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. */ import { Store } from "../../UIEventSource" import { GeoOperations } from "../../GeoOperations" import FeatureSource from "../FeatureSource" import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig" import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" import LineRenderingConfig from "../../../Models/ThemeConfig/LineRenderingConfig" export default class RenderingMultiPlexerFeatureSource { public readonly features: Store< (any & { pointRenderingIndex: number | undefined lineRenderingIndex: number | undefined })[] > private readonly pointRenderings: { rendering: PointRenderingConfig; index: number }[] private centroidRenderings: { rendering: PointRenderingConfig; index: number }[] private projectedCentroidRenderings: { rendering: PointRenderingConfig; index: number }[] private startRenderings: { rendering: PointRenderingConfig; index: number }[] private endRenderings: { rendering: PointRenderingConfig; index: number }[] private hasCentroid: boolean private lineRenderObjects: LineRenderingConfig[] private inspectFeature( feat, addAsPoint: (feat, rendering, centerpoint: [number, number]) => void, withIndex: any[] ) { if (feat.geometry.type === "Point") { for (const rendering of this.pointRenderings) { withIndex.push({ ...feat, pointRenderingIndex: rendering.index, }) } } else { // This is a a line: add the centroids let centerpoint: [number, number] = undefined let projectedCenterPoint: [number, number] = undefined if (this.hasCentroid) { centerpoint = GeoOperations.centerpointCoordinates(feat) if (this.projectedCentroidRenderings.length > 0) { projectedCenterPoint = <[number, number]>( GeoOperations.nearestPoint(feat, centerpoint).geometry.coordinates ) } } for (const rendering of this.centroidRenderings) { addAsPoint(feat, rendering, centerpoint) } if (feat.geometry.type === "LineString") { for (const rendering of this.projectedCentroidRenderings) { addAsPoint(feat, rendering, projectedCenterPoint) } // Add start- and endpoints const coordinates = feat.geometry.coordinates for (const rendering of this.startRenderings) { addAsPoint(feat, rendering, coordinates[0]) } for (const rendering of this.endRenderings) { const coordinate = coordinates[coordinates.length - 1] addAsPoint(feat, rendering, coordinate) } } else { for (const rendering of this.projectedCentroidRenderings) { addAsPoint(feat, rendering, centerpoint) } } // AT last, add it 'as is' to what we should render for (let i = 0; i < this.lineRenderObjects.length; i++) { withIndex.push({ ...feat, lineRenderingIndex: i, }) } } } constructor(upstream: FeatureSource, layer: LayerConfig) { const pointRenderObjects: { rendering: PointRenderingConfig; index: number }[] = layer.mapRendering.map((r, i) => ({ rendering: r, index: i, })) this.pointRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("point")) this.centroidRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("centroid") ) this.projectedCentroidRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("projected_centerpoint") ) this.startRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("start")) this.endRenderings = pointRenderObjects.filter((r) => r.rendering.location.has("end")) this.hasCentroid = this.centroidRenderings.length > 0 || this.projectedCentroidRenderings.length > 0 this.lineRenderObjects = layer.lineRendering this.features = upstream.features.map((features) => { if (features === undefined) { return undefined } const withIndex: any[] = [] function addAsPoint(feat, rendering, coordinate) { const patched = { ...feat, pointRenderingIndex: rendering.index, } patched.geometry = { type: "Point", coordinates: coordinate, } withIndex.push(patched) } for (const f of features) { const feat = f.feature if (feat === undefined) { continue } this.inspectFeature(feat, addAsPoint, withIndex) } return withIndex }) } }