forked from MapComplete/MapComplete
		
	
		
			
				
	
	
		
			134 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
			
		
		
	
	
			134 lines
		
	
	
	
		
			4.5 KiB
		
	
	
	
		
			TypeScript
		
	
	
	
	
	
| import Script from "../Script"
 | |
| import fs from "fs"
 | |
| import { Feature, FeatureCollection } from "geojson"
 | |
| import { GeoOperations } from "../../src/Logic/GeoOperations"
 | |
| 
 | |
| // vite-node scripts/velopark/compare.ts -- velopark_all.geojson osm_with_velopark_link_.geojson
 | |
| class Compare extends Script {
 | |
|     compare(
 | |
|         veloId: string,
 | |
|         osmParking: Feature,
 | |
|         veloParking: Feature
 | |
|     ): {
 | |
|         distance: number
 | |
|         ref: string
 | |
|         osmid: string
 | |
|         diffs: {
 | |
|             osm: string
 | |
|             velopark: string
 | |
|             key: string
 | |
|         }[]
 | |
|     } {
 | |
|         const osmCenterpoint = GeoOperations.centerpointCoordinates(osmParking)
 | |
|         const veloparkCenterpoint = GeoOperations.centerpointCoordinates(veloParking)
 | |
|         const distance = Math.round(
 | |
|             GeoOperations.distanceBetween(osmCenterpoint, veloparkCenterpoint)
 | |
|         )
 | |
|         const diffs: { osm: string; velopark: string; key: string }[] = []
 | |
| 
 | |
|         const allKeys = new Set<string>(
 | |
|             Object.keys(osmParking.properties).concat(Object.keys(veloParking.properties))
 | |
|         )
 | |
|         for (const key of allKeys) {
 | |
|             if (["name", "numberOfLevels", "id"].indexOf(key) >= 0) {
 | |
|                 continue // We don't care about these tags
 | |
|             }
 | |
|             if (osmParking.properties[key] === veloParking.properties[key]) {
 | |
|                 continue
 | |
|             }
 | |
|             if (Number(osmParking.properties[key]) === veloParking.properties[key]) {
 | |
|                 continue
 | |
|             }
 | |
|             if (veloParking.properties[key] === undefined) {
 | |
|                 continue
 | |
|             }
 | |
|             diffs.push({
 | |
|                 key,
 | |
|                 osm: osmParking.properties[key],
 | |
|                 velopark: veloParking.properties[key],
 | |
|             })
 | |
|         }
 | |
|         let osmid =
 | |
|             osmParking.properties["@id"] ??
 | |
|             osmParking["id"] /*Not in the properties, that is how overpass returns it*/
 | |
|         if (!osmid.startsWith("http")) {
 | |
|             osmid = "https://openstreetmap.org/" + osmid
 | |
|         }
 | |
| 
 | |
|         return {
 | |
|             ref: veloId,
 | |
|             osmid,
 | |
|             distance,
 | |
|             diffs,
 | |
|         }
 | |
|     }
 | |
| 
 | |
|     async main(args: string[]): Promise<void> {
 | |
|         let [velopark, osm, key] = args
 | |
|         if (velopark === undefined || osm === undefined) {
 | |
|             console.log(
 | |
|                 "Needed argument: velopark.geojson osm.geojson [key]\nThe key is optional and will be `ref:velopark` by default\nUse overpass to get a geojson with ref:velopark"
 | |
|             )
 | |
|             return
 | |
|         }
 | |
|         key ??= "ref:velopark"
 | |
|         const veloparkData: FeatureCollection = JSON.parse(fs.readFileSync(velopark, "utf-8"))
 | |
|         const osmData: FeatureCollection = JSON.parse(fs.readFileSync(osm, "utf-8"))
 | |
| 
 | |
|         const veloparkById: Record<string, Feature> = {}
 | |
|         for (const parking of veloparkData.features) {
 | |
|             veloparkById[parking.properties[key] ?? parking.properties.url] = parking
 | |
|         }
 | |
| 
 | |
|         const diffs = []
 | |
|         for (const parking of osmData.features) {
 | |
|             const veloId = parking.properties[key]
 | |
|             const veloparking = veloparkById[veloId]
 | |
|             if (veloparking === undefined) {
 | |
|                 console.error("No velopark entry found for", veloId)
 | |
|                 continue
 | |
|             }
 | |
|             console.log("Veloparking is", veloparking)
 | |
|             diffs.push(this.compare(veloId, parking, veloparking))
 | |
|         }
 | |
|         console.log(
 | |
|             "Found ",
 | |
|             diffs.length,
 | |
|             " items with differences between OSM and the provided data"
 | |
|         )
 | |
| 
 | |
|         const maxDistance = Math.max(...diffs.map((d) => d.distance))
 | |
|         const distanceBins = []
 | |
|         const binSize = 5
 | |
|         for (let i = 0; i < Math.ceil(maxDistance / binSize); i++) {
 | |
|             distanceBins.push(0)
 | |
|         }
 | |
|         for (const diff of diffs) {
 | |
|             const bin = Math.floor(diff.distance / binSize)
 | |
|             distanceBins[bin] += 1
 | |
|         }
 | |
| 
 | |
|         fs.writeFileSync(
 | |
|             "report_diff.json",
 | |
|             JSON.stringify(
 | |
|                 {
 | |
|                     diffs,
 | |
|                     distanceBins,
 | |
|                     binSize,
 | |
|                     "#binsize": "Every bin increases with this amount in meter",
 | |
|                 },
 | |
|                 null,
 | |
|                 "  "
 | |
|             )
 | |
|         )
 | |
|         console.log("Written report_diff.json")
 | |
|     }
 | |
| 
 | |
|     constructor() {
 | |
|         super(
 | |
|             "Compares a velopark geojson with OSM geojson. Usage: `compare velopark.geojson osm.geojson [key-to-compare-on]`. If key-to-compare-on is not given, `ref:velopark` will be used"
 | |
|         )
 | |
|     }
 | |
| }
 | |
| 
 | |
| new Compare().run()
 |