forked from MapComplete/MapComplete
		
	Various small fixes
This commit is contained in:
		
							parent
							
								
									261cde3e28
								
							
						
					
					
						commit
						1af5e44ad4
					
				
					 6 changed files with 176 additions and 20 deletions
				
			
		| 
						 | 
					@ -7,7 +7,6 @@ import FeatureSource from "../FeatureSource";
 | 
				
			||||||
import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig";
 | 
					import PointRenderingConfig from "../../../Models/ThemeConfig/PointRenderingConfig";
 | 
				
			||||||
import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../../../Models/ThemeConfig/LayerConfig";
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					 | 
				
			||||||
export default class RenderingMultiPlexerFeatureSource {
 | 
					export default class RenderingMultiPlexerFeatureSource {
 | 
				
			||||||
    public readonly features: UIEventSource<(any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined })[]>;
 | 
					    public readonly features: UIEventSource<(any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined })[]>;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -29,7 +28,7 @@ export default class RenderingMultiPlexerFeatureSource {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const lineRenderObjects = layer.lineRendering
 | 
					                const lineRenderObjects = layer.lineRendering
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                const withIndex: (any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined })[] = [];
 | 
					                const withIndex: (any & { pointRenderingIndex: number | undefined, lineRenderingIndex: number | undefined, multiLineStringIndex: number | undefined })[] = [];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                function addAsPoint(feat, rendering, coordinate) {
 | 
					                function addAsPoint(feat, rendering, coordinate) {
 | 
				
			||||||
| 
						 | 
					@ -69,11 +68,18 @@ export default class RenderingMultiPlexerFeatureSource {
 | 
				
			||||||
                                const coordinate = coordinates[coordinates.length - 1]
 | 
					                                const coordinate = coordinates[coordinates.length - 1]
 | 
				
			||||||
                                addAsPoint(feat, rendering, coordinate)
 | 
					                                addAsPoint(feat, rendering, coordinate)
 | 
				
			||||||
                            }
 | 
					                            }
 | 
				
			||||||
 | 
					                            for (let i = 0; i < lineRenderObjects.length; i++) {
 | 
				
			||||||
 | 
					                                withIndex.push({
 | 
				
			||||||
 | 
					                                    ...feat,
 | 
				
			||||||
 | 
					                                    lineRenderingIndex: i
 | 
				
			||||||
 | 
					                                })
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                        if (feat.geometry.type === "MultiLineString") {
 | 
					                        if (feat.geometry.type === "MultiLineString") {
 | 
				
			||||||
                            const lineList = feat.geometry.coordinates
 | 
					                            const lineList: [number, number][][] = feat.geometry.coordinates
 | 
				
			||||||
                            for (const coordinates of lineList) {
 | 
					                            for (let i1 = 0; i1 < lineList.length; i1++) {
 | 
				
			||||||
 | 
					                                const coordinates = lineList[i1];
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                for (const rendering of startRenderings) {
 | 
					                                for (const rendering of startRenderings) {
 | 
				
			||||||
                                    const coordinate = coordinates[0]
 | 
					                                    const coordinate = coordinates[0]
 | 
				
			||||||
| 
						 | 
					@ -83,19 +89,25 @@ export default class RenderingMultiPlexerFeatureSource {
 | 
				
			||||||
                                    const coordinate = coordinates[coordinates.length - 1]
 | 
					                                    const coordinate = coordinates[coordinates.length - 1]
 | 
				
			||||||
                                    addAsPoint(feat, rendering, coordinate)
 | 
					                                    addAsPoint(feat, rendering, coordinate)
 | 
				
			||||||
                                }
 | 
					                                }
 | 
				
			||||||
                            }
 | 
					 | 
				
			||||||
                        }
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                                for (let i = 0; i < lineRenderObjects.length; i++) {
 | 
					                                for (let i = 0; i < lineRenderObjects.length; i++) {
 | 
				
			||||||
                            withIndex.push({
 | 
					                                    const orig = {
 | 
				
			||||||
                                        ...feat,
 | 
					                                        ...feat,
 | 
				
			||||||
                                lineRenderingIndex: i
 | 
					                                        lineRenderingIndex: i,
 | 
				
			||||||
                            })
 | 
					                                        multiLineStringIndex: i1
 | 
				
			||||||
 | 
					                                    }
 | 
				
			||||||
 | 
					                                    orig.geometry.coordinates = coordinates
 | 
				
			||||||
 | 
					                                    orig.geometry.type = "LineString"
 | 
				
			||||||
 | 
					                                    withIndex.push(orig)
 | 
				
			||||||
 | 
					                                }
 | 
				
			||||||
 | 
					                            }
 | 
				
			||||||
                        }
 | 
					                        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                    }
 | 
					                    }
 | 
				
			||||||
                }
 | 
					                }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
                return withIndex;
 | 
					                return withIndex;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        );
 | 
					        );
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -3,7 +3,6 @@ import {BBox} from "./BBox";
 | 
				
			||||||
import togpx from "togpx"
 | 
					import togpx from "togpx"
 | 
				
			||||||
import Constants from "../Models/Constants";
 | 
					import Constants from "../Models/Constants";
 | 
				
			||||||
import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
					import LayerConfig from "../Models/ThemeConfig/LayerConfig";
 | 
				
			||||||
import {meta} from "@turf/turf";
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
export class GeoOperations {
 | 
					export class GeoOperations {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					@ -465,6 +464,151 @@ export class GeoOperations {
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
    
 | 
					    
 | 
				
			||||||
 | 
					    public static IdentifieCommonSegments(coordinatess: [number,number][][] ): {
 | 
				
			||||||
 | 
					        originalIndex: number,
 | 
				
			||||||
 | 
					        segmentShardWith: number[],
 | 
				
			||||||
 | 
					        coordinates: []
 | 
				
			||||||
 | 
					    }[]{
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        // An edge. Note that the edge might be reversed to fix the sorting condition:  start[0] < end[0] && (start[0] != end[0] || start[0] < end[1])
 | 
				
			||||||
 | 
					        type edge = {start: [number, number], end: [number, number], intermediate: [number,number][], members: {index:number, isReversed: boolean}[]}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // The strategy:
 | 
				
			||||||
 | 
					        // 1. Index _all_ edges from _every_ linestring. Index them by starting key, gather which relations run over them
 | 
				
			||||||
 | 
					        // 2. Join these edges back together - as long as their membership groups are the same
 | 
				
			||||||
 | 
					        // 3. Convert to results
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        const allEdgesByKey = new Map<string, edge>()
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        for (let index = 0; index < coordinatess.length; index++){
 | 
				
			||||||
 | 
					            const coordinates = coordinatess[index];
 | 
				
			||||||
 | 
					            for (let i = 0; i < coordinates.length - 1; i++){
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                const c0 = coordinates[i];
 | 
				
			||||||
 | 
					                const c1 = coordinates[i + 1]
 | 
				
			||||||
 | 
					                const isReversed = (c0[0] > c1[0]) || (c0[0] == c1[0] && c0[1] > c1[1])
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                let key : string
 | 
				
			||||||
 | 
					                if(isReversed){
 | 
				
			||||||
 | 
					                    key = ""+c1+";"+c0
 | 
				
			||||||
 | 
					                }else{
 | 
				
			||||||
 | 
					                    key = ""+c0+";"+c1
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                const member = {index, isReversed}
 | 
				
			||||||
 | 
					                if(allEdgesByKey.has(key)){
 | 
				
			||||||
 | 
					                    allEdgesByKey.get(key).members.push(member)
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                let edge : edge;
 | 
				
			||||||
 | 
					                if(!isReversed){
 | 
				
			||||||
 | 
					                    edge = {
 | 
				
			||||||
 | 
					                        start : c0,
 | 
				
			||||||
 | 
					                        end: c1,
 | 
				
			||||||
 | 
					                        members: [member],
 | 
				
			||||||
 | 
					                        intermediate: []
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }else{
 | 
				
			||||||
 | 
					                    edge = {
 | 
				
			||||||
 | 
					                        start : c1,
 | 
				
			||||||
 | 
					                        end: c0,
 | 
				
			||||||
 | 
					                        members: [member],
 | 
				
			||||||
 | 
					                        intermediate: []
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                allEdgesByKey.set(key, edge)
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        // Lets merge them back together!
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        let didMergeSomething = false;
 | 
				
			||||||
 | 
					        let allMergedEdges = Array.from(allEdgesByKey.values())
 | 
				
			||||||
 | 
					        const allEdgesByStartPoint = new Map<string, edge[]>()
 | 
				
			||||||
 | 
					        for (const edge of allMergedEdges) {
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            edge.members.sort((m0, m1) => m0.index - m1.index)
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            const kstart = edge.start+""
 | 
				
			||||||
 | 
					            if(!allEdgesByStartPoint.has(kstart)){
 | 
				
			||||||
 | 
					                allEdgesByStartPoint.set(kstart, [])
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            allEdgesByStartPoint.get(kstart).push(edge)
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        function membersAreCompatible(first:edge, second:edge): boolean{
 | 
				
			||||||
 | 
					            // There must be an exact match between the members
 | 
				
			||||||
 | 
					            if(first.members === second.members){
 | 
				
			||||||
 | 
					                return true
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            if(first.members.length !== second.members.length){
 | 
				
			||||||
 | 
					                return false
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Members are sorted and have the same length, so we can check quickly
 | 
				
			||||||
 | 
					            for (let i = 0; i < first.members.length; i++) {
 | 
				
			||||||
 | 
					                const m0 = first.members[i]
 | 
				
			||||||
 | 
					                const m1 = second.members[i]
 | 
				
			||||||
 | 
					                if(m0.index !== m1.index || m0.isReversed !== m1.isReversed){
 | 
				
			||||||
 | 
					                    return false
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            // Allrigth, they are the same, lets mark this permanently
 | 
				
			||||||
 | 
					            second.members = first.members
 | 
				
			||||||
 | 
					            return true
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        do{
 | 
				
			||||||
 | 
					            didMergeSomething = false
 | 
				
			||||||
 | 
					            // We use 'allMergedEdges' as our running list
 | 
				
			||||||
 | 
					            const consumed = new Set<edge>()
 | 
				
			||||||
 | 
					            for (const edge of allMergedEdges) {
 | 
				
			||||||
 | 
					                // Can we make this edge longer at the end?
 | 
				
			||||||
 | 
					                if(consumed.has(edge)){
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                console.log("Considering edge", edge)
 | 
				
			||||||
 | 
					                const matchingEndEdges = allEdgesByStartPoint.get(edge.end+"") 
 | 
				
			||||||
 | 
					                console.log("Matchign endpoints:", matchingEndEdges)
 | 
				
			||||||
 | 
					                if(matchingEndEdges === undefined){
 | 
				
			||||||
 | 
					                    continue
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                
 | 
				
			||||||
 | 
					                for (let i = 0; i < matchingEndEdges.length; i++){
 | 
				
			||||||
 | 
					                    const endEdge = matchingEndEdges[i];
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if(consumed.has(endEdge)){
 | 
				
			||||||
 | 
					                        continue
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    if(!membersAreCompatible(edge, endEdge)){
 | 
				
			||||||
 | 
					                        continue
 | 
				
			||||||
 | 
					                    }
 | 
				
			||||||
 | 
					                    
 | 
				
			||||||
 | 
					                    // We can make the segment longer!
 | 
				
			||||||
 | 
					                    didMergeSomething = true
 | 
				
			||||||
 | 
					                    console.log("Merging ", edge, "with ", endEdge)
 | 
				
			||||||
 | 
					                    edge.intermediate.push(edge.end)
 | 
				
			||||||
 | 
					                    edge.end = endEdge.end
 | 
				
			||||||
 | 
					                    consumed.add(endEdge)
 | 
				
			||||||
 | 
					                    matchingEndEdges.splice(i, 1)
 | 
				
			||||||
 | 
					                    break;
 | 
				
			||||||
 | 
					                }
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					            allMergedEdges = allMergedEdges.filter(edge => !consumed.has(edge));
 | 
				
			||||||
 | 
					            
 | 
				
			||||||
 | 
					        }while(didMergeSomething)
 | 
				
			||||||
 | 
					        
 | 
				
			||||||
 | 
					        return []
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
}
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -55,7 +55,7 @@ export default class ScrollableFullScreen extends UIElement {
 | 
				
			||||||
            if (!isShown.data) {
 | 
					            if (!isShown.data) {
 | 
				
			||||||
                return;
 | 
					                return;
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            if (hash === undefined || hash === "") {
 | 
					            if (hash === undefined || hash === "" || hash !== hashToShow) {
 | 
				
			||||||
                isShown.setData(false)
 | 
					                isShown.setData(false)
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
        })
 | 
					        })
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -24,7 +24,7 @@ export default class LocationInput extends InputElement<Loc> implements MinimapO
 | 
				
			||||||
                osmTags: {and: []}
 | 
					                osmTags: {and: []}
 | 
				
			||||||
            },
 | 
					            },
 | 
				
			||||||
            mapRendering: [{
 | 
					            mapRendering: [{
 | 
				
			||||||
                location: ["point"],
 | 
					                location: ["point","centroid"],
 | 
				
			||||||
                icon: "./assets/svg/crosshair-empty.svg"
 | 
					                icon: "./assets/svg/crosshair-empty.svg"
 | 
				
			||||||
            }]
 | 
					            }]
 | 
				
			||||||
        }, "matchpoint icon", true
 | 
					        }, "matchpoint icon", true
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -152,7 +152,7 @@ export default class ShowDataLayer {
 | 
				
			||||||
                continue
 | 
					                continue
 | 
				
			||||||
            }
 | 
					            }
 | 
				
			||||||
            try {
 | 
					            try {
 | 
				
			||||||
                if ((feat.geometry.type === "LineString" || feat.geometry.type === "MultiLineString")) {
 | 
					                if (feat.geometry.type === "LineString") {
 | 
				
			||||||
                    const self = this;
 | 
					                    const self = this;
 | 
				
			||||||
                    const coords = L.GeoJSON.coordsToLatLngs(feat.geometry.coordinates)
 | 
					                    const coords = L.GeoJSON.coordsToLatLngs(feat.geometry.coordinates)
 | 
				
			||||||
                    const tagsSource = this.allElements?.addOrGetElement(feat) ?? new UIEventSource<any>(feat.properties);
 | 
					                    const tagsSource = this.allElements?.addOrGetElement(feat) ?? new UIEventSource<any>(feat.properties);
 | 
				
			||||||
| 
						 | 
					@ -270,7 +270,7 @@ export default class ShowDataLayer {
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        let infobox: FeatureInfoBox = undefined;
 | 
					        let infobox: FeatureInfoBox = undefined;
 | 
				
			||||||
 | 
					
 | 
				
			||||||
        const id = `popup-${feature.properties.id}-${feature.geometry.type}-${this.showDataLayerid}-${this._cleanCount}-${feature.pointRenderingIndex ?? feature.lineRenderingIndex}`
 | 
					        const id = `popup-${feature.properties.id}-${feature.geometry.type}-${this.showDataLayerid}-${this._cleanCount}-${feature.pointRenderingIndex ?? feature.lineRenderingIndex}-${feature.multiLineStringIndex ?? ""}`
 | 
				
			||||||
        popup.setContent(`<div style='height: 65vh' id='${id}'>Popup for ${feature.properties.id} ${feature.geometry.type} ${id} is loading</div>`)
 | 
					        popup.setContent(`<div style='height: 65vh' id='${id}'>Popup for ${feature.properties.id} ${feature.geometry.type} ${id} is loading</div>`)
 | 
				
			||||||
        leafletLayer.on("popupopen", () => {
 | 
					        leafletLayer.on("popupopen", () => {
 | 
				
			||||||
            if (infobox === undefined) {
 | 
					            if (infobox === undefined) {
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
| 
						 | 
					@ -6,7 +6,7 @@
 | 
				
			||||||
    "osmTags": "user:location=yes",
 | 
					    "osmTags": "user:location=yes",
 | 
				
			||||||
    "maxCacheAge": 0
 | 
					    "maxCacheAge": 0
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "title": {
 | 
					  "#title": {
 | 
				
			||||||
    "render": "Your travelled path"
 | 
					    "render": "Your travelled path"
 | 
				
			||||||
  },
 | 
					  },
 | 
				
			||||||
  "tagRenderings": [
 | 
					  "tagRenderings": [
 | 
				
			||||||
| 
						 | 
					@ -18,10 +18,10 @@
 | 
				
			||||||
    },
 | 
					    },
 | 
				
			||||||
    "export_as_gpx"
 | 
					    "export_as_gpx"
 | 
				
			||||||
  ],
 | 
					  ],
 | 
				
			||||||
  "name": "Your track",
 | 
					  "#name": "Your track",
 | 
				
			||||||
  "mapRendering": [
 | 
					  "mapRendering": [
 | 
				
			||||||
    {
 | 
					    {
 | 
				
			||||||
      "width": 3,
 | 
					      "width": 0,
 | 
				
			||||||
      "color": "#bb000077"
 | 
					      "color": "#bb000077"
 | 
				
			||||||
    }
 | 
					    }
 | 
				
			||||||
  ]
 | 
					  ]
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue