forked from MapComplete/MapComplete
		
	
		
			
	
	
		
			92 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
		
		
			
		
	
	
			92 lines
		
	
	
	
		
			3.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| 
								 | 
							
								import {appendFileSync, existsSync, readFileSync, writeFileSync} from "fs";
							 | 
						||
| 
								 | 
							
								import {GeoOperations} from "../../Logic/GeoOperations";
							 | 
						||
| 
								 | 
							
								import ScriptUtils from "../ScriptUtils";
							 | 
						||
| 
								 | 
							
								import {Utils} from "../../Utils";
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								async function main(args: string[]) {
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const pointCandidates = JSON.parse(readFileSync(args[0], "utf8"))
							 | 
						||
| 
								 | 
							
								    const postcodes = JSON.parse(readFileSync(args[1], "utf8"))
							 | 
						||
| 
								 | 
							
								    const output = args[2] ?? "centralCoordinates.csv"
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    const perPostCode = new Map<string, any[]>()
							 | 
						||
| 
								 | 
							
								    
							 | 
						||
| 
								 | 
							
								    const alreadyLoaded = new Set<number>()
							 | 
						||
| 
								 | 
							
								    if(existsSync(output)){
							 | 
						||
| 
								 | 
							
								      const lines =  readFileSync(output, "UTF8").split("\n")
							 | 
						||
| 
								 | 
							
								        lines.shift()
							 | 
						||
| 
								 | 
							
								        lines.forEach(line => {
							 | 
						||
| 
								 | 
							
								          const postalCode = Number( line.split(",")[0])
							 | 
						||
| 
								 | 
							
								            alreadyLoaded.add(postalCode)
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								    }else{
							 | 
						||
| 
								 | 
							
								        writeFileSync(output,"postal_code,lon,lat\n","UTF-8")
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (const boundary of postcodes.features) {
							 | 
						||
| 
								 | 
							
								        const postcode = boundary.properties.nouveau_PO
							 | 
						||
| 
								 | 
							
								        if(alreadyLoaded.has(Number(postcode))){
							 | 
						||
| 
								 | 
							
								            console.log("Skipping ", postcode, "as already loaded")
							 | 
						||
| 
								 | 
							
								            continue
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (perPostCode.has(postcode)) {
							 | 
						||
| 
								 | 
							
								            perPostCode.get(postcode).push(boundary)
							 | 
						||
| 
								 | 
							
								        } else {
							 | 
						||
| 
								 | 
							
								            perPostCode.set(postcode, [boundary])
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								    for (const postcode of Array.from(perPostCode.keys())) {
							 | 
						||
| 
								 | 
							
								        const boundaries = perPostCode.get(postcode)
							 | 
						||
| 
								 | 
							
								        const candidates = []
							 | 
						||
| 
								 | 
							
								        for (const boundary of boundaries) {
							 | 
						||
| 
								 | 
							
								            for (const candidate of pointCandidates.features) {
							 | 
						||
| 
								 | 
							
								                if (!GeoOperations.inside(candidate, boundary)) {
							 | 
						||
| 
								 | 
							
								                    // console.log(JSON.stringify(candidate))
							 | 
						||
| 
								 | 
							
								                    continue
							 | 
						||
| 
								 | 
							
								                }
							 | 
						||
| 
								 | 
							
								                candidates.push(candidate.geometry.coordinates)
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								        if (candidates.length === 0) {
							 | 
						||
| 
								 | 
							
								            console.log("Postcode ", postcode, "has", candidates.length, "candidates, using centerpoint instead")
							 | 
						||
| 
								 | 
							
								            candidates.push(...boundaries.map(boundary => GeoOperations.centerpointCoordinates(boundary)))
							 | 
						||
| 
								 | 
							
								        }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								        const url = "https://staging.anyways.eu/routing-api/v1/routes?access_token=postal_code_script&turn_by_turn=false&format=geojson&language=en"
							 | 
						||
| 
								 | 
							
								        const depPoints :[number,number][] = Utils.NoNull( await Promise.all(candidates.map(async candidate => {
							 | 
						||
| 
								 | 
							
								            try{
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								                const result = await ScriptUtils.DownloadJSON(url + "&loc=" + candidate.join("%2C") + "&loc=3.22000%2C51.21577&profile=car.short")
							 | 
						||
| 
								 | 
							
								                const depPoint = result.features.filter(f => f.geometry.type === "LineString")[0].geometry.coordinates[0]
							 | 
						||
| 
								 | 
							
								                return <[number,number]>[depPoint[0], depPoint[1]] // Drop elevation
							 | 
						||
| 
								 | 
							
								            }catch(e){
							 | 
						||
| 
								 | 
							
								                console.error("No result or could not calculate a route")
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        })))
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        const centers = boundaries.map(b => GeoOperations.centerpointCoordinates(b))
							 | 
						||
| 
								 | 
							
								        const center = GeoOperations.centerpointCoordinates({
							 | 
						||
| 
								 | 
							
								            type:"Feature",
							 | 
						||
| 
								 | 
							
								            geometry:{
							 | 
						||
| 
								 | 
							
								                type:"LineString",
							 | 
						||
| 
								 | 
							
								                coordinates: centers
							 | 
						||
| 
								 | 
							
								            }
							 | 
						||
| 
								 | 
							
								        })
							 | 
						||
| 
								 | 
							
								        
							 | 
						||
| 
								 | 
							
								        depPoints.sort((c0, c1) => GeoOperations.distanceBetween(c0, center) - GeoOperations.distanceBetween(c1, center))
							 | 
						||
| 
								 | 
							
								        console.log("Sorted departure point candidates for ",postcode," are ", JSON.stringify(depPoints))
							 | 
						||
| 
								 | 
							
								        appendFileSync(output,[postcode, ...depPoints[0]].join(", ")+"\n","UTF-8")
							 | 
						||
| 
								 | 
							
								    }
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								}
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								
							 | 
						||
| 
								 | 
							
								let args = [...process.argv]
							 | 
						||
| 
								 | 
							
								args.splice(0, 2)
							 | 
						||
| 
								 | 
							
								main(args).then(_ => console.log("Done!"))
							 |