forked from MapComplete/MapComplete
		
	Download needed relations completely, fixes 873
This commit is contained in:
		
							parent
							
								
									732d4621ae
								
							
						
					
					
						commit
						4fd40c6935
					
				
					 6 changed files with 418 additions and 88 deletions
				
			
		|  | @ -10,6 +10,7 @@ import {BBox} from "../../BBox"; | ||||||
| import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"; | import LayoutConfig from "../../../Models/ThemeConfig/LayoutConfig"; | ||||||
| import {Or} from "../../Tags/Or"; | import {Or} from "../../Tags/Or"; | ||||||
| import {TagsFilter} from "../../Tags/TagsFilter"; | import {TagsFilter} from "../../Tags/TagsFilter"; | ||||||
|  | import {OsmObject} from "../../Osm/OsmObject"; | ||||||
| 
 | 
 | ||||||
| /** | /** | ||||||
|  * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' |  * If a tile is needed (requested via the UIEventSource in the constructor), will download the appropriate tile and pass it via 'handleTile' | ||||||
|  | @ -31,7 +32,7 @@ export default class OsmFeatureSource { | ||||||
|     private readonly allowedTags: TagsFilter; |     private readonly allowedTags: TagsFilter; | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      *  |      * | ||||||
|      * @param options: allowedFeatures is normally calculated from the layoutToUse |      * @param options: allowedFeatures is normally calculated from the layoutToUse | ||||||
|      */ |      */ | ||||||
|     constructor(options: { |     constructor(options: { | ||||||
|  | @ -81,7 +82,7 @@ export default class OsmFeatureSource { | ||||||
| 
 | 
 | ||||||
|             for (const neededTile of neededTiles) { |             for (const neededTile of neededTiles) { | ||||||
|                 this.downloadedTiles.add(neededTile) |                 this.downloadedTiles.add(neededTile) | ||||||
|                 this.LoadTile(...Tiles.tile_from_index(neededTile)) |                 await this.LoadTile(...Tiles.tile_from_index(neededTile)) | ||||||
|             } |             } | ||||||
|         } catch (e) { |         } catch (e) { | ||||||
|             console.error(e) |             console.error(e) | ||||||
|  | @ -90,7 +91,33 @@ export default class OsmFeatureSource { | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     private LoadTile(z, x, y): void { |     /** | ||||||
|  |      * The requested tile might only contain part of the relation. | ||||||
|  |      * | ||||||
|  |      * This method will download the full relation and return it as geojson if it was incomplete. | ||||||
|  |      * If the feature is already complete (or is not a relation), the feature will be returned | ||||||
|  |      */ | ||||||
|  |     private async patchIncompleteRelations(feature: {properties: {id: string}},  | ||||||
|  |                                            originalJson: {elements: {type: "node" | "way" | "relation", id: number, } []}): Promise<any> { | ||||||
|  |         if(!feature.properties.id.startsWith("relation")){ | ||||||
|  |             return feature | ||||||
|  |         } | ||||||
|  |         const relationSpec = originalJson.elements.find(f => "relation/"+f.id === feature.properties.id) | ||||||
|  |         const members : {type: string, ref: number}[] = relationSpec["members"] | ||||||
|  |         for (const member of members) { | ||||||
|  |             const isFound = originalJson.elements.some(f => f.id === member.ref && f.type === member.type) | ||||||
|  |             if (isFound) { | ||||||
|  |                 continue | ||||||
|  |             } | ||||||
|  |              | ||||||
|  |             // This member is missing. We redownload the entire relation instead
 | ||||||
|  |             console.debug("Fetching incomplete relation "+feature.properties.id) | ||||||
|  |             return (await OsmObject.DownloadObjectAsync(feature.properties.id)).asGeoJson() | ||||||
|  |         } | ||||||
|  |         return feature; | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|  |     private async LoadTile(z, x, y): Promise<void> { | ||||||
|         if (z > 25) { |         if (z > 25) { | ||||||
|             throw "This is an absurd high zoom level" |             throw "This is an absurd high zoom level" | ||||||
|         } |         } | ||||||
|  | @ -102,8 +129,11 @@ export default class OsmFeatureSource { | ||||||
|         const bbox = BBox.fromTile(z, x, y) |         const bbox = BBox.fromTile(z, x, y) | ||||||
|         const url = `${this._backend}/api/0.6/map?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}` |         const url = `${this._backend}/api/0.6/map?bbox=${bbox.minLon},${bbox.minLat},${bbox.maxLon},${bbox.maxLat}` | ||||||
| 
 | 
 | ||||||
|         Utils.downloadJson(url).then(osmJson => { |         let error = undefined; | ||||||
|  |         try { | ||||||
|  |             const osmJson = await Utils.downloadJson(url) | ||||||
|             try { |             try { | ||||||
|  | 
 | ||||||
|                 console.log("Got tile", z, x, y, "from the osm api") |                 console.log("Got tile", z, x, y, "from the osm api") | ||||||
|                 this.rawDataHandlers.forEach(handler => handler(osmJson, Tiles.tile_index(z, x, y))) |                 this.rawDataHandlers.forEach(handler => handler(osmJson, Tiles.tile_index(z, x, y))) | ||||||
|                 const geojson = OsmToGeoJson.default(osmJson, |                 const geojson = OsmToGeoJson.default(osmJson, | ||||||
|  | @ -112,10 +142,15 @@ export default class OsmFeatureSource { | ||||||
|                         flatProperties: true |                         flatProperties: true | ||||||
|                     }); |                     }); | ||||||
| 
 | 
 | ||||||
|  | 
 | ||||||
|                 // The geojson contains _all_ features at the given location
 |                 // The geojson contains _all_ features at the given location
 | ||||||
|                 // We only keep what is needed
 |                 // We only keep what is needed
 | ||||||
| 
 | 
 | ||||||
|                 geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties)) |                 geojson.features = geojson.features.filter(feature => this.allowedTags.matchesProperties(feature.properties)) | ||||||
|  | 
 | ||||||
|  |                 for (let i = 0; i < geojson.features.length; i++) { | ||||||
|  |                     geojson.features[i] = await this.patchIncompleteRelations(geojson.features[i], osmJson) | ||||||
|  |                 } | ||||||
|                 geojson.features.forEach(f => { |                 geojson.features.forEach(f => { | ||||||
|                     f.properties["_backend"] = this._backend |                     f.properties["_backend"] = this._backend | ||||||
|                 }) |                 }) | ||||||
|  | @ -131,22 +166,25 @@ export default class OsmFeatureSource { | ||||||
|                 if (this.options.markTileVisited) { |                 if (this.options.markTileVisited) { | ||||||
|                     this.options.markTileVisited(index) |                     this.options.markTileVisited(index) | ||||||
|                 } |                 } | ||||||
|             } catch (e) { |             }catch(e){ | ||||||
|                 console.error("Weird error: ", e) |                 console.error("PANIC: got the tile from the OSM-api, but something crashed handling this tile") | ||||||
|  |                 error = e; | ||||||
|             } |             } | ||||||
|         }) |              | ||||||
|             .catch(e => { |         } catch (e) { | ||||||
|                 console.error("Could not download tile", z, x, y, "due to", e, "; retrying with smaller bounds") |             console.error("Could not download tile", z, x, y, "due to", e, "; retrying with smaller bounds") | ||||||
|                 if (e === "rate limited") { |             if (e === "rate limited") { | ||||||
|                     return; |  | ||||||
|                 } |  | ||||||
|                 this.LoadTile(z + 1, x * 2, y * 2) |  | ||||||
|                 this.LoadTile(z + 1, 1 + x * 2, y * 2) |  | ||||||
|                 this.LoadTile(z + 1, x * 2, 1 + y * 2) |  | ||||||
|                 this.LoadTile(z + 1, 1 + x * 2, 1 + y * 2) |  | ||||||
|                 return; |                 return; | ||||||
|             }) |             } | ||||||
|  |             await this.LoadTile(z + 1, x * 2, y * 2) | ||||||
|  |             await this.LoadTile(z + 1, 1 + x * 2, y * 2) | ||||||
|  |             await this.LoadTile(z + 1, x * 2, 1 + y * 2) | ||||||
|  |             await this.LoadTile(z + 1, 1 + x * 2, 1 + y * 2) | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|  |         if(error !== undefined){ | ||||||
|  |             throw error; | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |  | ||||||
|  | @ -1,8 +1,8 @@ | ||||||
| import {Utils} from "../../Utils"; | import {Utils} from "../../Utils"; | ||||||
| import * as polygon_features from "../../assets/polygon-features.json"; | import * as polygon_features from "../../assets/polygon-features.json"; | ||||||
| import {Store, Stores, UIEventSource} from "../UIEventSource"; | import {Store, UIEventSource} from "../UIEventSource"; | ||||||
| import {BBox} from "../BBox"; | import {BBox} from "../BBox"; | ||||||
| 
 | import * as OsmToGeoJson from "osmtogeojson"; | ||||||
| 
 | 
 | ||||||
| export abstract class OsmObject { | export abstract class OsmObject { | ||||||
| 
 | 
 | ||||||
|  | @ -38,6 +38,7 @@ export abstract class OsmObject { | ||||||
|             throw "Backend URL must begin with http" |             throw "Backend URL must begin with http" | ||||||
|         } |         } | ||||||
|         this.backendURL = url; |         this.backendURL = url; | ||||||
|  |         this.DownloadObject("id/5") | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     public static DownloadObject(id: string, forceRefresh: boolean = false): Store<OsmObject> { |     public static DownloadObject(id: string, forceRefresh: boolean = false): Store<OsmObject> { | ||||||
|  | @ -77,10 +78,10 @@ export abstract class OsmObject { | ||||||
|             return undefined; |             return undefined; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const full = (id.startsWith("way")) ? "/full" : ""; |         const full = (!id.startsWith("node")) ? "/full" : ""; | ||||||
|         const url = `${OsmObject.backendURL}api/0.6/${id}${full}`; |         const url = `${OsmObject.backendURL}api/0.6/${id}${full}`; | ||||||
|         const rawData = await Utils.downloadJsonCached(url, 1000) |         const rawData = await Utils.downloadJsonCached(url, 10000) | ||||||
|         if(rawData === undefined){ |         if (rawData === undefined) { | ||||||
|             return undefined |             return undefined | ||||||
|         } |         } | ||||||
|         // A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way)
 |         // A full query might contain more then just the requested object (e.g. nodes that are part of a way, where we only want the way)
 | ||||||
|  | @ -127,7 +128,7 @@ export abstract class OsmObject { | ||||||
|         return data.elements.map(wayInfo => { |         return data.elements.map(wayInfo => { | ||||||
|             const rel = new OsmRelation(wayInfo.id) |             const rel = new OsmRelation(wayInfo.id) | ||||||
|             rel.LoadData(wayInfo) |             rel.LoadData(wayInfo) | ||||||
|             rel.SaveExtraData(wayInfo) |             rel.SaveExtraData(wayInfo, undefined) | ||||||
|             return rel |             return rel | ||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  | @ -196,7 +197,13 @@ export abstract class OsmObject { | ||||||
|                     break; |                     break; | ||||||
|                 case("relation"): |                 case("relation"): | ||||||
|                     osmObject = new OsmRelation(idN); |                     osmObject = new OsmRelation(idN); | ||||||
|                     osmObject.SaveExtraData(element, []) |                     const allGeojsons = OsmToGeoJson.default({elements}, | ||||||
|  |                         // @ts-ignore
 | ||||||
|  |                         { | ||||||
|  |                             flatProperties: true | ||||||
|  |                         }); | ||||||
|  |                     const feature = allGeojsons.features.find(f => f.id === osmObject.type + "/" + osmObject.id) | ||||||
|  |                     osmObject.SaveExtraData(element, feature) | ||||||
|                     break; |                     break; | ||||||
|             } |             } | ||||||
| 
 | 
 | ||||||
|  | @ -218,7 +225,7 @@ export abstract class OsmObject { | ||||||
|             if (!tags.hasOwnProperty(tagsKey)) { |             if (!tags.hasOwnProperty(tagsKey)) { | ||||||
|                 continue |                 continue | ||||||
|             } |             } | ||||||
|             const polyGuide : { values: Set<string>; blacklist: boolean } = OsmObject.polygonFeatures.get(tagsKey) |             const polyGuide: { values: Set<string>; blacklist: boolean } = OsmObject.polygonFeatures.get(tagsKey) | ||||||
|             if (polyGuide === undefined) { |             if (polyGuide === undefined) { | ||||||
|                 continue |                 continue | ||||||
|             } |             } | ||||||
|  | @ -228,12 +235,12 @@ export abstract class OsmObject { | ||||||
|             } |             } | ||||||
|             // is the key contained? Then we have a match if the value is contained
 |             // is the key contained? Then we have a match if the value is contained
 | ||||||
|             const doesMatch = polyGuide.values.has(tags[tagsKey]) |             const doesMatch = polyGuide.values.has(tags[tagsKey]) | ||||||
|             if(polyGuide.blacklist){ |             if (polyGuide.blacklist) { | ||||||
|                 return !doesMatch |                 return !doesMatch | ||||||
|             } |             } | ||||||
|             return doesMatch |             return doesMatch | ||||||
|         } |         } | ||||||
|          | 
 | ||||||
|         return false; |         return false; | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  | @ -260,7 +267,7 @@ export abstract class OsmObject { | ||||||
| 
 | 
 | ||||||
|     public abstract asGeoJson(): any; |     public abstract asGeoJson(): any; | ||||||
| 
 | 
 | ||||||
|     abstract SaveExtraData(element: any, allElements: OsmObject[]); |     abstract SaveExtraData(element: any, allElements: OsmObject[] | any); | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Generates the changeset-XML for tags |      * Generates the changeset-XML for tags | ||||||
|  | @ -431,7 +438,7 @@ export class OsmWay extends OsmObject { | ||||||
|     private isPolygon(): boolean { |     private isPolygon(): boolean { | ||||||
|         // Compare lat and lon seperately, as the coordinate array might not be a reference to the same object
 |         // Compare lat and lon seperately, as the coordinate array might not be a reference to the same object
 | ||||||
|         if (this.coordinates[0][0] !== this.coordinates[this.coordinates.length - 1][0] || |         if (this.coordinates[0][0] !== this.coordinates[this.coordinates.length - 1][0] || | ||||||
|             this.coordinates[0][1] !== this.coordinates[this.coordinates.length - 1][1] ) { |             this.coordinates[0][1] !== this.coordinates[this.coordinates.length - 1][1]) { | ||||||
|             return false; // Not closed
 |             return false; // Not closed
 | ||||||
|         } |         } | ||||||
|         return OsmObject.isPolygon(this.tags) |         return OsmObject.isPolygon(this.tags) | ||||||
|  | @ -447,6 +454,8 @@ export class OsmRelation extends OsmObject { | ||||||
|         role: string |         role: string | ||||||
|     }[]; |     }[]; | ||||||
| 
 | 
 | ||||||
|  |     private geojson = undefined | ||||||
|  | 
 | ||||||
|     constructor(id: number) { |     constructor(id: number) { | ||||||
|         super("relation", id); |         super("relation", id); | ||||||
|     } |     } | ||||||
|  | @ -472,11 +481,15 @@ ${members}${tags}        </relation> | ||||||
| 
 | 
 | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     SaveExtraData(element) { |     SaveExtraData(element, geojson) { | ||||||
|         this.members = element.members; |         this.members = element.members; | ||||||
|  |         this.geojson = geojson | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     asGeoJson(): any { |     asGeoJson(): any { | ||||||
|  |         if (this.geojson !== undefined) { | ||||||
|  |             return this.geojson; | ||||||
|  |         } | ||||||
|         throw "Not Implemented" |         throw "Not Implemented" | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | @ -10,61 +10,269 @@ import {Tag} from "../../../Logic/Tags/Tag"; | ||||||
| import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"; | import LayerConfig from "../../../Models/ThemeConfig/LayerConfig"; | ||||||
| import {expect} from "chai"; | import {expect} from "chai"; | ||||||
| 
 | 
 | ||||||
| console.log(process.cwd()) |  | ||||||
| let data = JSON.parse(readFileSync("./test/Logic/FeatureSource/osmdata.json", "utf8")) |  | ||||||
| 
 | 
 | ||||||
|  | const expected = { | ||||||
|  |     "type": "Feature", | ||||||
|  |     "id": "relation/5759328", | ||||||
|  |     "properties": { | ||||||
|  |         "timestamp": "2022-06-10T00:46:55Z", | ||||||
|  |         "version": 6, | ||||||
|  |         "changeset": 122187206, | ||||||
|  |         "user": "Pieter Vander Vennet", | ||||||
|  |         "uid": 3818858, | ||||||
|  |         "amenity": "school", | ||||||
|  |         "isced:2011:level": "vocational_lower_secondary;vocational_upper_secondary", | ||||||
|  |         "name": "Koninklijk Technisch Atheneum Pro Technica", | ||||||
|  |         "school:gender": "mixed", | ||||||
|  |         "type": "multipolygon", | ||||||
|  |         "website": "http://ktahalle.be/", | ||||||
|  |         "id": "relation/5759328", | ||||||
|  |         "_backend":"https://osm.org" | ||||||
|  |     }, | ||||||
|  |     "geometry": { | ||||||
|  |         "type": "MultiPolygon", | ||||||
|  |         "coordinates": [ | ||||||
|  |             [ | ||||||
|  |                 [ | ||||||
|  |                     [ | ||||||
|  |                         4.2461832, | ||||||
|  |                         50.7335751 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2463167, | ||||||
|  |                         50.7336785 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2463473, | ||||||
|  |                         50.7337021 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2464497, | ||||||
|  |                         50.7337814 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2471698, | ||||||
|  |                         50.7343389 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2469541, | ||||||
|  |                         50.7344768 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2467571, | ||||||
|  |                         50.7346116 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2467727, | ||||||
|  |                         50.7346199 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2465714, | ||||||
|  |                         50.7347511 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2462398, | ||||||
|  |                         50.7349687 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2453546, | ||||||
|  |                         50.734601 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2451895, | ||||||
|  |                         50.7345103 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2448867, | ||||||
|  |                         50.7342629 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.244899, | ||||||
|  |                         50.7342069 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2461832, | ||||||
|  |                         50.7335751 | ||||||
|  |                     ] | ||||||
|  |                 ] | ||||||
|  |             ], | ||||||
|  |             [ | ||||||
|  |                 [ | ||||||
|  |                     [ | ||||||
|  |                         4.2444209, | ||||||
|  |                         50.7353737 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2439986, | ||||||
|  |                         50.7352034 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2440303, | ||||||
|  |                         50.7351755 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2440602, | ||||||
|  |                         50.7351058 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2439776, | ||||||
|  |                         50.7350326 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2439558, | ||||||
|  |                         50.7350132 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2438246, | ||||||
|  |                         50.7348961 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2437848, | ||||||
|  |                         50.73486 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2436555, | ||||||
|  |                         50.7347455 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2435905, | ||||||
|  |                         50.734689 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2435494, | ||||||
|  |                         50.7346601 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2435038, | ||||||
|  |                         50.7346256 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2434769, | ||||||
|  |                         50.7346026 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2430948, | ||||||
|  |                         50.734275 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2427978, | ||||||
|  |                         50.7340052 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2430556, | ||||||
|  |                         50.7338391 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2438957, | ||||||
|  |                         50.7334942 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2440204, | ||||||
|  |                         50.7336368 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2442806, | ||||||
|  |                         50.7338922 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2444173, | ||||||
|  |                         50.7340119 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2447379, | ||||||
|  |                         50.7342925 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2450107, | ||||||
|  |                         50.7345294 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2450236, | ||||||
|  |                         50.7346021 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2449643, | ||||||
|  |                         50.7347019 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.244711, | ||||||
|  |                         50.7350821 | ||||||
|  |                     ], | ||||||
|  |                     [ | ||||||
|  |                         4.2444209, | ||||||
|  |                         50.7353737 | ||||||
|  |                     ] | ||||||
|  |                 ] | ||||||
|  |             ] | ||||||
|  |         ] | ||||||
|  |     } | ||||||
|  | } | ||||||
|  | 
 | ||||||
|  | function test(done: () => void){ | ||||||
|  |     let fetchedTile = undefined; | ||||||
|  |     const neededTiles = new UIEventSource<number[]>([Tiles.tile_index(17, 67081, 44033)]); | ||||||
|  |     new OsmFeatureSource({ | ||||||
|  |         allowedFeatures: new Tag("amenity", "school"), | ||||||
|  |         handleTile: tile => { | ||||||
|  |             fetchedTile = tile | ||||||
|  |             const data = tile.features.data[0].feature | ||||||
|  |             expect(data.properties).deep.eq({ | ||||||
|  |                 id: 'relation/5759328', timestamp: '2022-06-10T00:46:55Z', | ||||||
|  |                 version: 6, | ||||||
|  |                 changeset: 122187206, | ||||||
|  |                 user: 'Pieter Vander Vennet', | ||||||
|  |                 uid: 3818858, | ||||||
|  |                 amenity: 'school', | ||||||
|  |                 'isced:2011:level': 'vocational_lower_secondary;vocational_upper_secondary', | ||||||
|  |                 name: 'Koninklijk Technisch Atheneum Pro Technica', | ||||||
|  |                 'school:gender': 'mixed', | ||||||
|  |                 type: 'multipolygon', | ||||||
|  |                 website: 'http://ktahalle.be/', | ||||||
|  |                 _backend: 'https://osm.org' | ||||||
|  |             }) | ||||||
|  |             expect(data.geometry.type).eq("MultiPolygon") | ||||||
|  |             expect(data).deep.eq(expected) | ||||||
|  |             done() | ||||||
|  |         }, | ||||||
|  |         isActive: new UIEventSource<boolean>(true), | ||||||
|  |         neededTiles, | ||||||
|  |         state: { | ||||||
|  |             osmConnection: { | ||||||
|  |                 Backend(): string { | ||||||
|  |                     return "https://osm.org" | ||||||
|  |                 } | ||||||
|  |             }, | ||||||
|  |             filteredLayers: new UIEventSource<FilteredLayer[]>([ | ||||||
|  |                 { | ||||||
|  |                     appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined), | ||||||
|  |                     layerDef: new LayerConfig({ | ||||||
|  |                         id: "school", | ||||||
|  |                         source: { | ||||||
|  |                             osmTags: "amenity=school" | ||||||
|  |                         }, | ||||||
|  |                         mapRendering: null | ||||||
|  |                     }), | ||||||
|  |                     isDisplayed: new UIEventSource<boolean>(true) | ||||||
|  |                 } | ||||||
|  |             ]) | ||||||
|  |         } | ||||||
|  |     }) | ||||||
|  | } | ||||||
| 
 | 
 | ||||||
| describe("OsmFeatureSource", () => { | describe("OsmFeatureSource", () => { | ||||||
| 
 | 
 | ||||||
|     it("should work", (done) => { |     it("downloading the full school should give a multipolygon", (done) => { | ||||||
|         ScriptUtils.fixUtils() |         ScriptUtils.fixUtils() | ||||||
|  |         let data = JSON.parse(readFileSync("./test/Logic/FeatureSource/osmdata.json", "utf8")) | ||||||
|         Utils.injectJsonDownloadForTests("https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244", data) |         Utils.injectJsonDownloadForTests("https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244", data) | ||||||
|         let fetchedTile = undefined; |         test(done) | ||||||
|         const neededTiles = new UIEventSource<number[]>([Tiles.tile_index(17, 67081, 44033)]); |     }) | ||||||
|         new OsmFeatureSource({ | 
 | ||||||
|             allowedFeatures: new Tag("amenity", "school"), |     it("downloading the partial school polygon should give a multipolygon", (done) => { | ||||||
|             handleTile: tile => { |         ScriptUtils.fixUtils() | ||||||
|                 fetchedTile = tile |         Utils.injectJsonDownloadForTests("https://www.openstreetmap.org/api/0.6/relation/5759328/full", JSON.parse(readFileSync("./test/data/relation_5759328.json","UTF-8"))) | ||||||
|                 const data = tile.features.data[0].feature |         let data = JSON.parse(readFileSync("./test/Logic/FeatureSource/small_box.json", "utf8")) | ||||||
|                 expect(data.properties).deep.eq({ |         Utils.injectJsonDownloadForTests("https://osm.org/api/0.6/map?bbox=4.24346923828125,50.732978448277514,4.2462158203125,50.73471682490244", data) | ||||||
|                     id: 'relation/5759328', timestamp: '2022-06-10T00:46:55Z', |         test(done) | ||||||
|                     version: 6, |  | ||||||
|                     changeset: 122187206, |  | ||||||
|                     user: 'Pieter Vander Vennet', |  | ||||||
|                     uid: 3818858, |  | ||||||
|                     amenity: 'school', |  | ||||||
|                     'isced:2011:level': 'vocational_lower_secondary;vocational_upper_secondary', |  | ||||||
|                     name: 'Koninklijk Technisch Atheneum Pro Technica', |  | ||||||
|                     'school:gender': 'mixed', |  | ||||||
|                     type: 'multipolygon', |  | ||||||
|                     website: 'http://ktahalle.be/', |  | ||||||
|                     _backend: 'https://osm.org' |  | ||||||
|                 }) |  | ||||||
|                 expect(data.geometry.type).eq("MultiPolygon") |  | ||||||
|                 done() |  | ||||||
|             }, |  | ||||||
|             isActive: new UIEventSource<boolean>(true), |  | ||||||
|             neededTiles, |  | ||||||
|             state: { |  | ||||||
|                 osmConnection: { |  | ||||||
|                     Backend(): string { |  | ||||||
|                         return "https://osm.org" |  | ||||||
|                     } |  | ||||||
|                 }, |  | ||||||
|                 filteredLayers: new UIEventSource<FilteredLayer[]>([ |  | ||||||
|                     { |  | ||||||
|                         appliedFilters: new UIEventSource<Map<string, FilterState>>(undefined), |  | ||||||
|                         layerDef: new LayerConfig({ |  | ||||||
|                             id: "school", |  | ||||||
|                             source: { |  | ||||||
|                                 osmTags: "amenity=school" |  | ||||||
|                             }, |  | ||||||
|                             mapRendering: null |  | ||||||
|                         }), |  | ||||||
|                         isDisplayed: new UIEventSource<boolean>(true) |  | ||||||
|                     } |  | ||||||
|                 ]) |  | ||||||
|             } |  | ||||||
|         }) |  | ||||||
|     }) |     }) | ||||||
| }) | }) | ||||||
							
								
								
									
										1
									
								
								test/Logic/FeatureSource/small_box.json
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										1
									
								
								test/Logic/FeatureSource/small_box.json
									
										
									
									
									
										Normal file
									
								
							
										
											
												File diff suppressed because one or more lines are too long
											
										
									
								
							|  | @ -71,7 +71,7 @@ describe("RelationSplitHandler", () => { | ||||||
|     ) |     ) | ||||||
| 
 | 
 | ||||||
|     Utils.injectJsonDownloadForTests( |     Utils.injectJsonDownloadForTests( | ||||||
|         "https://www.openstreetmap.org/api/0.6/relation/9572808", |         "https://www.openstreetmap.org/api/0.6/relation/9572808/full", | ||||||
|         { |         { | ||||||
|             "version": "0.6", |             "version": "0.6", | ||||||
|             "generator": "CGImap 0.8.5 (3128319 spike-07.openstreetmap.org)", |             "generator": "CGImap 0.8.5 (3128319 spike-07.openstreetmap.org)", | ||||||
|  | @ -266,7 +266,7 @@ describe("RelationSplitHandler", () => { | ||||||
|         } |         } | ||||||
|     ) |     ) | ||||||
|     Utils.injectJsonDownloadForTests( |     Utils.injectJsonDownloadForTests( | ||||||
|         "https://www.openstreetmap.org/api/0.6/relation/4374576", |         "https://www.openstreetmap.org/api/0.6/relation/4374576/full", | ||||||
|         { |         { | ||||||
|             "version": "0.6", |             "version": "0.6", | ||||||
|             "generator": "CGImap 0.8.5 (1266692 spike-06.openstreetmap.org)", |             "generator": "CGImap 0.8.5 (1266692 spike-06.openstreetmap.org)", | ||||||
|  | @ -552,7 +552,7 @@ describe("RelationSplitHandler", () => { | ||||||
| 
 | 
 | ||||||
|     it("should split all cycling relation (split 295132739)", |     it("should split all cycling relation (split 295132739)", | ||||||
|         async () => { |         async () => { | ||||||
|             // Lets mimick a split action of https://www.openstreetmap.org/way/295132739
 |             // Lets mimic a split action of https://www.openstreetmap.org/way/295132739
 | ||||||
| 
 | 
 | ||||||
|             const relation: OsmRelation = <OsmRelation>await OsmObject.DownloadObjectAsync("relation/9572808") |             const relation: OsmRelation = <OsmRelation>await OsmObject.DownloadObjectAsync("relation/9572808") | ||||||
|             const originalNodeIds = [5273988967, |             const originalNodeIds = [5273988967, | ||||||
|  |  | ||||||
|  | @ -2,22 +2,92 @@ import {describe} from 'mocha' | ||||||
| import {expect} from 'chai' | import {expect} from 'chai' | ||||||
| import {OsmObject} from "../../../Logic/Osm/OsmObject"; | import {OsmObject} from "../../../Logic/Osm/OsmObject"; | ||||||
| import {Utils} from "../../../Utils"; | import {Utils} from "../../../Utils"; | ||||||
|  | import ScriptUtils from "../../../scripts/ScriptUtils"; | ||||||
|  | import {readFileSync} from "fs"; | ||||||
| 
 | 
 | ||||||
| describe("OsmObject", () => { | describe("OsmObject", () => { | ||||||
|      | 
 | ||||||
|     describe("download referencing ways", () => { |     describe("download referencing ways", () => { | ||||||
| 
 | 
 | ||||||
|         Utils.injectJsonDownloadForTests( |         Utils.injectJsonDownloadForTests( | ||||||
|             "https://www.openstreetmap.org/api/0.6/node/1124134958/ways", {"version":"0.6","generator":"CGImap 0.8.6 (49805 spike-06.openstreetmap.org)","copyright":"OpenStreetMap and contributors","attribution":"http://www.openstreetmap.org/copyright","license":"http://opendatacommons.org/licenses/odbl/1-0/","elements":[{"type":"way","id":97038428,"timestamp":"2019-06-19T12:26:24Z","version":6,"changeset":71399984,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1124134958,323729212,323729351,2542460408,187073405],"tags":{"highway":"residential","name":"Brugs-Kerkhofstraat","sett:pattern":"arc","surface":"sett"}},{"type":"way","id":97038434,"timestamp":"2019-06-19T12:26:24Z","version":5,"changeset":71399984,"user":"Pieter Vander Vennet","uid":3818858,"nodes":[1124134958,1124135024,187058607],"tags":{"bicycle":"use_sidepath","highway":"residential","name":"Kerkhofblommenstraat","sett:pattern":"arc","surface":"sett"}},{"type":"way","id":97038435,"timestamp":"2017-12-21T21:41:08Z","version":4,"changeset":54826837,"user":"Jakka","uid":2403313,"nodes":[1124134958,2576628889,1124135035,5298371485,5298371495],"tags":{"bicycle":"use_sidepath","highway":"residential","name":"Kerkhofblommenstraat"}},{"type":"way","id":251446313,"timestamp":"2019-01-07T19:22:47Z","version":4,"changeset":66106872,"user":"M!dgard","uid":763799,"nodes":[1124134958,5243143198,4555715455],"tags":{"foot":"yes","highway":"service"}}]}) |             "https://www.openstreetmap.org/api/0.6/node/1124134958/ways", { | ||||||
|  |                 "version": "0.6", | ||||||
|  |                 "generator": "CGImap 0.8.6 (49805 spike-06.openstreetmap.org)", | ||||||
|  |                 "copyright": "OpenStreetMap and contributors", | ||||||
|  |                 "attribution": "http://www.openstreetmap.org/copyright", | ||||||
|  |                 "license": "http://opendatacommons.org/licenses/odbl/1-0/", | ||||||
|  |                 "elements": [{ | ||||||
|  |                     "type": "way", | ||||||
|  |                     "id": 97038428, | ||||||
|  |                     "timestamp": "2019-06-19T12:26:24Z", | ||||||
|  |                     "version": 6, | ||||||
|  |                     "changeset": 71399984, | ||||||
|  |                     "user": "Pieter Vander Vennet", | ||||||
|  |                     "uid": 3818858, | ||||||
|  |                     "nodes": [1124134958, 323729212, 323729351, 2542460408, 187073405], | ||||||
|  |                     "tags": { | ||||||
|  |                         "highway": "residential", | ||||||
|  |                         "name": "Brugs-Kerkhofstraat", | ||||||
|  |                         "sett:pattern": "arc", | ||||||
|  |                         "surface": "sett" | ||||||
|  |                     } | ||||||
|  |                 }, { | ||||||
|  |                     "type": "way", | ||||||
|  |                     "id": 97038434, | ||||||
|  |                     "timestamp": "2019-06-19T12:26:24Z", | ||||||
|  |                     "version": 5, | ||||||
|  |                     "changeset": 71399984, | ||||||
|  |                     "user": "Pieter Vander Vennet", | ||||||
|  |                     "uid": 3818858, | ||||||
|  |                     "nodes": [1124134958, 1124135024, 187058607], | ||||||
|  |                     "tags": { | ||||||
|  |                         "bicycle": "use_sidepath", | ||||||
|  |                         "highway": "residential", | ||||||
|  |                         "name": "Kerkhofblommenstraat", | ||||||
|  |                         "sett:pattern": "arc", | ||||||
|  |                         "surface": "sett" | ||||||
|  |                     } | ||||||
|  |                 }, { | ||||||
|  |                     "type": "way", | ||||||
|  |                     "id": 97038435, | ||||||
|  |                     "timestamp": "2017-12-21T21:41:08Z", | ||||||
|  |                     "version": 4, | ||||||
|  |                     "changeset": 54826837, | ||||||
|  |                     "user": "Jakka", | ||||||
|  |                     "uid": 2403313, | ||||||
|  |                     "nodes": [1124134958, 2576628889, 1124135035, 5298371485, 5298371495], | ||||||
|  |                     "tags": {"bicycle": "use_sidepath", "highway": "residential", "name": "Kerkhofblommenstraat"} | ||||||
|  |                 }, { | ||||||
|  |                     "type": "way", | ||||||
|  |                     "id": 251446313, | ||||||
|  |                     "timestamp": "2019-01-07T19:22:47Z", | ||||||
|  |                     "version": 4, | ||||||
|  |                     "changeset": 66106872, | ||||||
|  |                     "user": "M!dgard", | ||||||
|  |                     "uid": 763799, | ||||||
|  |                     "nodes": [1124134958, 5243143198, 4555715455], | ||||||
|  |                     "tags": {"foot": "yes", "highway": "service"} | ||||||
|  |                 }] | ||||||
|  |             }) | ||||||
| 
 | 
 | ||||||
| 
 | 
 | ||||||
|         it("should download referencing ways",   |         it("should download referencing ways", | ||||||
|             async () => { |             async () => { | ||||||
|              | 
 | ||||||
|              | 
 | ||||||
|                 const ways = await OsmObject.DownloadReferencingWays("node/1124134958") |                 const ways = await OsmObject.DownloadReferencingWays("node/1124134958") | ||||||
|                 expect(ways).not.undefined |                 expect(ways).not.undefined | ||||||
|                 expect(ways).length(4) |                 expect(ways).length(4) | ||||||
|             }) |             }) | ||||||
|  |          | ||||||
|  |          | ||||||
|  |         it("should download full OSM-relations", async () => { | ||||||
|  |             ScriptUtils.fixUtils() | ||||||
|  |             Utils.injectJsonDownloadForTests("https://www.openstreetmap.org/api/0.6/relation/5759328/full", JSON.parse(readFileSync("./test/data/relation_5759328.json","UTF-8"))) | ||||||
|  |             const r = await OsmObject.DownloadObjectAsync("relation/5759328").then(x => x) | ||||||
|  |             const geojson = r.asGeoJson(); | ||||||
|  |             expect(geojson.geometry.type).eq("MultiPolygon") | ||||||
|  |         }) | ||||||
|     }) |     }) | ||||||
|  | 
 | ||||||
| }) | }) | ||||||
|  |  | ||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue