From 8aa830f15e5d1d47c7fcf8addc24ab0d62e13d9c Mon Sep 17 00:00:00 2001 From: pietervdvn Date: Thu, 27 May 2021 18:55:12 +0200 Subject: [PATCH] Properly render a downloaded way, fix #297 --- Logic/Osm/OsmObject.ts | 20 ++++- Utils.ts | 43 +++++++++- assets/polygon-features.json | 157 +++++++++++++++++++++++++++++++++++ package.json | 3 +- 4 files changed, 218 insertions(+), 5 deletions(-) create mode 100644 assets/polygon-features.json diff --git a/Logic/Osm/OsmObject.ts b/Logic/Osm/OsmObject.ts index a3d6c8535..b303a3063 100644 --- a/Logic/Osm/OsmObject.ts +++ b/Logic/Osm/OsmObject.ts @@ -130,7 +130,7 @@ export abstract class OsmObject { osmObject.SaveExtraData(element, []) break; } - osmObject.LoadData(element) + osmObject?.LoadData(element) objects.push(osmObject) } return objects; @@ -321,7 +321,15 @@ export class OsmWay extends OsmObject { let latSum = 0 let lonSum = 0 + console.log("element is", element, "nodes are", allNodes) + + const nodeDict = new Map() for (const node of allNodes) { + nodeDict.set(node.id, node) + } + + for (const nodeId of element.nodes) { + const node = nodeDict.get(nodeId) const cp = node.centerpoint(); this.coordinates.push(cp); latSum = cp[0] @@ -338,11 +346,19 @@ export class OsmWay extends OsmObject { "type": "Feature", "properties": this.tags, "geometry": { - "type": "LineString", + "type": this.isPolygon() ? "Polygon" : "LineString", "coordinates": this.coordinates.map(c => [c[1], c[0]]) } } } + + private isPolygon(): boolean { + if (this.coordinates[0] !== this.coordinates[this.coordinates.length - 1]) { + return false; // Not closed + } + return Utils.isPolygon(this.tags) + + } } export class OsmRelation extends OsmObject { diff --git a/Utils.ts b/Utils.ts index 2c613af86..506cfd9ff 100644 --- a/Utils.ts +++ b/Utils.ts @@ -1,4 +1,5 @@ import * as colors from "./assets/colors.json" +import * as polygon_features from "./assets/polygon-features.json" export class Utils { @@ -8,11 +9,30 @@ export class Utils { * This is a workaround and yet another hack */ public static runningFromConsole = false; - public static readonly assets_path = "./assets/svg/"; + // Empty + private static polygonFeatures = Utils.constructPolygonFeatures() private static knownKeys = ["addExtraTags", "and", "calculatedTags", "changesetmessage", "clustering", "color", "condition", "customCss", "dashArray", "defaultBackgroundId", "description", "descriptionTail", "doNotDownload", "enableAddNewPoints", "enableBackgroundLayerSelection", "enableGeolocation", "enableLayers", "enableMoreQuests", "enableSearch", "enableShareScreen", "enableUserBadge", "freeform", "hideFromOverview", "hideInAnswer", "icon", "iconOverlays", "iconSize", "id", "if", "ifnot", "isShown", "key", "language", "layers", "lockLocation", "maintainer", "mappings", "maxzoom", "maxZoom", "minNeededElements", "minzoom", "multiAnswer", "name", "or", "osmTags", "passAllFeatures", "presets", "question", "render", "roaming", "roamingRenderings", "rotation", "shortDescription", "socialImage", "source", "startLat", "startLon", "startZoom", "tagRenderings", "tags", "then", "title", "titleIcons", "type", "version", "wayHandling", "widenFactor", "width"] private static extraKeys = ["nl", "en", "fr", "de", "pt", "es", "name", "phone", "email", "amenity", "leisure", "highway", "building", "yes", "no", "true", "false"] + public static isPolygon(tags: any): boolean { + for (const tagsKey in tags) { + if (!tags.hasOwnProperty(tagsKey)) { + continue + } + const polyGuide = Utils.polygonFeatures.get(tagsKey) + if (polyGuide === undefined) { + continue + } + if ((polyGuide.values === null)) { + // We match all + return !polyGuide.blacklist + } + // is the key contained? + return polyGuide.values.has(tags[tagsKey]) + } + } + static EncodeXmlValue(str) { if (typeof str !== "string") { str = "" + str @@ -161,7 +181,7 @@ export class Utils { static Merge(source: any, target: any) { for (const key in source) { - if(!source.hasOwnProperty(key)){ + if (!source.hasOwnProperty(key)) { continue } const sourceV = source[key]; @@ -326,6 +346,25 @@ export class Utils { return bestColor ?? hex; } + private static constructPolygonFeatures(): Map, blacklist: boolean }> { + const result = new Map, blacklist: boolean }>(); + + for (const polygonFeature of polygon_features) { + const key = polygonFeature.key; + + if (polygonFeature.polygon === "all") { + result.set(key, {values: null, blacklist: false}) + continue + } + + const blacklist = polygonFeature.polygon === "blacklist" + result.set(key, {values: new Set(polygonFeature.values), blacklist: blacklist}) + + } + + return result; + } + private static tile2long(x, z) { return (x / Math.pow(2, z) * 360 - 180); } diff --git a/assets/polygon-features.json b/assets/polygon-features.json new file mode 100644 index 000000000..8a86d16f8 --- /dev/null +++ b/assets/polygon-features.json @@ -0,0 +1,157 @@ +[ + { + "key": "building", + "polygon": "all" + }, + { + "key": "highway", + "polygon": "whitelist", + "values": [ + "services", + "rest_area", + "escape", + "elevator" + ] + }, + { + "key": "natural", + "polygon": "blacklist", + "values": [ + "coastline", + "cliff", + "ridge", + "arete", + "tree_row" + ] + }, + { + "key": "landuse", + "polygon": "all" + }, + { + "key": "waterway", + "polygon": "whitelist", + "values": [ + "riverbank", + "dock", + "boatyard", + "dam" + ] + }, + { + "key": "amenity", + "polygon": "all" + }, + { + "key": "leisure", + "polygon": "all" + }, + { + "key": "barrier", + "polygon": "whitelist", + "values": [ + "city_wall", + "ditch", + "hedge", + "retaining_wall", + "wall", + "spikes" + ] + }, + { + "key": "railway", + "polygon": "whitelist", + "values": [ + "station", + "turntable", + "roundhouse", + "platform" + ] + }, + { + "key": "area", + "polygon": "all" + }, + { + "key": "boundary", + "polygon": "all" + }, + { + "key": "man_made", + "polygon": "blacklist", + "values": [ + "cutline", + "embankment", + "pipeline" + ] + }, + { + "key": "power", + "polygon": "whitelist", + "values": [ + "plant", + "substation", + "generator", + "transformer" + ] + }, + { + "key": "place", + "polygon": "all" + }, + { + "key": "shop", + "polygon": "all" + }, + { + "key": "aeroway", + "polygon": "blacklist", + "values": [ + "taxiway" + ] + }, + { + "key": "tourism", + "polygon": "all" + }, + { + "key": "historic", + "polygon": "all" + }, + { + "key": "public_transport", + "polygon": "all" + }, + { + "key": "office", + "polygon": "all" + }, + { + "key": "building:part", + "polygon": "all" + }, + { + "key": "military", + "polygon": "all" + }, + { + "key": "ruins", + "polygon": "all" + }, + { + "key": "area:highway", + "polygon": "all" + }, + { + "key": "craft", + "polygon": "all" + }, + { + "key": "golf", + "polygon": "all" + }, + { + "key": "indoor", + "polygon": "all" + } +] diff --git a/package.json b/package.json index 9333c77dd..90adc2312 100644 --- a/package.json +++ b/package.json @@ -12,6 +12,7 @@ "test": "ts-node test/TestAll.ts", "init": "npm ci && npm run generate && npm run generate:editor-layer-index && npm run generate:layouts && npm run clean", "generate:editor-layer-index": "cd assets/ && wget https://osmlab.github.io/editor-layer-index/imagery.geojson --output-document=editor-layer-index.json", + "generate:polygon-features": "cd assets/ && wget https://raw.githubusercontent.com/tyrasd/osm-polygon-features/master/polygon-features.json --output-document=polygon-features.json", "generate:images": "ts-node scripts/generateIncludedImages.ts", "generate:translations": "ts-node scripts/generateTranslations.ts", "generate:layouts": "ts-node scripts/generateLayouts.ts", @@ -27,7 +28,7 @@ "reset:layeroverview": "echo '{\"layers\":[], \"themes\":[]}' > ./assets/generated/known_layers_and_themes.json", "generate": "mkdir -p ./assets/generated && npm run reset:layeroverview && npm run generate:images && npm run generate:translations && npm run generate:licenses && npm run generate:licenses && npm run generate:layeroverview", "build": "rm -rf dist/ && npm run generate && parcel build --public-url ./ *.html assets/** assets/**/** assets/**/**/** vendor/* vendor/*/*", - "prepare-deploy": "npm run generate && npm run test && npm run generate:editor-layer-index && npm run generate:layeroverview && npm run generate:layouts && npm run build && rm -rf .cache && npm run generate:docs", + "prepare-deploy": "npm run generate:contributor-list && npm run generate && npm run test && npm run generate:editor-layer-index && npm run generate:layeroverview && npm run generate:layouts && npm run build && rm -rf .cache && npm run generate:docs", "deploy:staging": "npm run prepare-deploy && rm -rf /home/pietervdvn/git/pietervdvn.github.io/Staging/* && cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/Staging/ && cd /home/pietervdvn/git/pietervdvn.github.io/ && git add * && git commit -m 'New MapComplete Version' && git push && cd - && npm run clean", "deploy:pietervdvn": "cd /home/pietervdvn/git/pietervdvn.github.io/ && git pull && cd - && npm run prepare-deploy && rm -rf /home/pietervdvn/git/pietervdvn.github.io/MapComplete/* && cp -r dist/* /home/pietervdvn/git/pietervdvn.github.io/MapComplete/ && cd /home/pietervdvn/git/pietervdvn.github.io/ && git add * && git commit -m 'New MapComplete Version' && git push && cd - && npm run clean", "deploy:production": "cd /home/pietervdvn/git/pietervdvn.github.io/ && git pull && cd - && rm -rf ./assets/generated && npm run prepare-deploy && npm run optimize-images && rm -rf /home/pietervdvn/git/mapcomplete.github.io/* && cp -r dist/* /home/pietervdvn/git/mapcomplete.github.io/ && cd /home/pietervdvn/git/mapcomplete.github.io/ && echo \"mapcomplete.osm.be\" > CNAME && git add * && git commit -m 'New MapComplete Version' && git push && cd - && npm run clean && npm run gittag",