| 
									
										
										
										
											2021-10-22 18:53:07 +02:00
										 |  |  | /** | 
					
						
							| 
									
										
										
										
											2022-04-22 16:09:55 +02:00
										 |  |  |  * This feature source helps the ShowDataLayer class: it introduces the necessary extra features and indicates with what renderConfig it should be rendered. | 
					
						
							| 
									
										
										
										
											2021-10-22 18:53:07 +02:00
										 |  |  |  */ | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  | import { Store } from "../../UIEventSource" | 
					
						
							|  |  |  | import { GeoOperations } from "../../GeoOperations" | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | import FeatureSource from "../FeatureSource" | 
					
						
							|  |  |  | import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig" | 
					
						
							|  |  |  | import LayerConfig from "../../../Models/ThemeConfig/LayerConfig" | 
					
						
							|  |  |  | import LineRenderingConfig from "../../../Models/ThemeConfig/LineRenderingConfig" | 
					
						
							| 
									
										
										
										
											2021-10-22 18:53:07 +02:00
										 |  |  | 
 | 
					
						
							|  |  |  | export default class RenderingMultiPlexerFeatureSource { | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     public readonly features: Store< | 
					
						
							|  |  |  |         (any & { | 
					
						
							|  |  |  |             pointRenderingIndex: number | undefined | 
					
						
							|  |  |  |             lineRenderingIndex: number | undefined | 
					
						
							|  |  |  |         })[] | 
					
						
							|  |  |  |     > | 
					
						
							|  |  |  |     private readonly pointRenderings: { rendering: PointRenderingConfig; index: number }[] | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |     private readonly centroidRenderings: { rendering: PointRenderingConfig; index: number }[] | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |     private readonly projectedCentroidRenderings: { | 
					
						
							|  |  |  |         rendering: PointRenderingConfig | 
					
						
							|  |  |  |         index: number | 
					
						
							|  |  |  |     }[] | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |     private readonly startRenderings: { rendering: PointRenderingConfig; index: number }[] | 
					
						
							|  |  |  |     private readonly endRenderings: { rendering: PointRenderingConfig; index: number }[] | 
					
						
							|  |  |  |     private readonly hasCentroid: boolean | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private lineRenderObjects: LineRenderingConfig[] | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |     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 | 
					
						
							|  |  |  |         }) | 
					
						
							|  |  |  |     } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |     /** | 
					
						
							|  |  |  |      * For every source feature, adds the necessary rendering-features | 
					
						
							|  |  |  |      */ | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |     private inspectFeature( | 
					
						
							|  |  |  |         feat, | 
					
						
							|  |  |  |         addAsPoint: (feat, rendering, centerpoint: [number, number]) => void, | 
					
						
							|  |  |  |         withIndex: any[] | 
					
						
							|  |  |  |     ) { | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |         if (feat.geometry.type === "Point") { | 
					
						
							|  |  |  |             for (const rendering of this.pointRenderings) { | 
					
						
							|  |  |  |                 withIndex.push({ | 
					
						
							|  |  |  |                     ...feat, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     pointRenderingIndex: rendering.index, | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |         } else if (feat.geometry.type === "MultiPolygon") { | 
					
						
							|  |  |  |             if (this.centroidRenderings.length > 0 || this.projectedCentroidRenderings.length > 0) { | 
					
						
							| 
									
										
										
										
											2022-12-16 13:45:07 +01:00
										 |  |  |                 const centerpoints: [number, number][] = (<[number, number][][][]>( | 
					
						
							|  |  |  |                     feat.geometry.coordinates | 
					
						
							|  |  |  |                 )).map((rings) => | 
					
						
							|  |  |  |                     GeoOperations.centerpointCoordinates({ | 
					
						
							|  |  |  |                         type: "Feature", | 
					
						
							|  |  |  |                         properties: {}, | 
					
						
							|  |  |  |                         geometry: { type: "Polygon", coordinates: rings }, | 
					
						
							|  |  |  |                     }) | 
					
						
							|  |  |  |                 ) | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |                 for (const centroidRendering of this.centroidRenderings) { | 
					
						
							|  |  |  |                     for (const centerpoint of centerpoints) { | 
					
						
							|  |  |  |                         addAsPoint(feat, centroidRendering, centerpoint) | 
					
						
							|  |  |  |                     } | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  | 
 | 
					
						
							|  |  |  |                 for (const centroidRendering of this.projectedCentroidRenderings) { | 
					
						
							|  |  |  |                     for (const centerpoint of centerpoints) { | 
					
						
							|  |  |  |                         addAsPoint(feat, centroidRendering, 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, | 
					
						
							|  |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |         } else { | 
					
						
							| 
									
										
										
										
											2022-12-09 17:53:25 +01:00
										 |  |  |             // This is a a line or polygon: add the centroids
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             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 | 
					
						
							|  |  |  |                     ) | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |             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) | 
					
						
							|  |  |  |                 } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             } else { | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |                 for (const rendering of this.projectedCentroidRenderings) { | 
					
						
							|  |  |  |                     addAsPoint(feat, rendering, centerpoint) | 
					
						
							|  |  |  |                 } | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  | 
 | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |             // AT last, add it 'as is' to what we should render
 | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |             for (let i = 0; i < this.lineRenderObjects.length; i++) { | 
					
						
							|  |  |  |                 withIndex.push({ | 
					
						
							|  |  |  |                     ...feat, | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  |                     lineRenderingIndex: i, | 
					
						
							| 
									
										
										
										
											2022-06-21 22:56:14 +02:00
										 |  |  |                 }) | 
					
						
							|  |  |  |             } | 
					
						
							|  |  |  |         } | 
					
						
							|  |  |  |     } | 
					
						
							| 
									
										
										
										
											2022-09-08 21:40:48 +02:00
										 |  |  | } |