forked from MapComplete/MapComplete
		
	Merge branch 'develop' into RobinLinde-patch-1
This commit is contained in:
		
						commit
						35812efec4
					
				
					 121 changed files with 1300 additions and 328 deletions
				
			
		|  | @ -17,14 +17,17 @@ import { ChangeDescription } from "../src/Logic/Osm/Actions/ChangeDescription" | |||
| import OsmObjectDownloader from "../src/Logic/Osm/OsmObjectDownloader" | ||||
| import { OsmObject } from "../src/Logic/Osm/OsmObject" | ||||
| import { createReadStream } from "node:fs" | ||||
| import { File } from 'buffer'; | ||||
| import { open } from 'node:fs/promises'; | ||||
| import { File } from "buffer" | ||||
| import { open } from "node:fs/promises" | ||||
| import { UploadableTag } from "../src/Logic/Tags/TagTypes" | ||||
| 
 | ||||
| 
 | ||||
| export class ImgurToPanoramax extends Script { | ||||
|     private readonly panoramax = new PanoramaxUploader( | ||||
|         Constants.panoramax.url, | ||||
|         Constants.panoramax.token, | ||||
|     ) | ||||
| 
 | ||||
|     private readonly panoramax = new PanoramaxUploader(Constants.panoramax.url, Constants.panoramax.token) | ||||
|     private readonly alreadyUploaded: Record<string, string> = {} | ||||
| 
 | ||||
|     private _imageDirectory: string | ||||
|     private _licenseDirectory: string | ||||
|  | @ -36,22 +39,32 @@ export class ImgurToPanoramax extends Script { | |||
|         ccbysa: "f3d02893-b4c1-4cd6-8b27-e27ab57eb59a", | ||||
|     } as const | ||||
| 
 | ||||
| 
 | ||||
|     constructor() { | ||||
|         super( | ||||
|             "Queries OSM for 'imgur'-images, uploads them to Panoramax and creates a changeset to update OSM", | ||||
|         ) | ||||
|     } | ||||
| 
 | ||||
|     async uploadImage(key: string, feat: Feature, sequences: ({ | ||||
|         id: string; | ||||
|         "stats:items": { count: number } | ||||
|     })[]): Promise<UploadableTag | undefined> { | ||||
|     async uploadImage( | ||||
|         key: string, | ||||
|         feat: Feature, | ||||
|         sequences: { | ||||
|             id: string | ||||
|             "stats:items": { count: number } | ||||
|         }[], | ||||
|     ): Promise<UploadableTag | undefined> { | ||||
|         const v = feat.properties[key] | ||||
|         if (!v) { | ||||
|             return undefined | ||||
|         } | ||||
|         const imageHash = v.split("/").at(-1).split(".").at(0) | ||||
| 
 | ||||
|         if (this.alreadyUploaded[imageHash]) { | ||||
|             const panohash = this.alreadyUploaded[imageHash] | ||||
|             return new And([new Tag(key.replace("image", panohash), panohash), new Tag(key, "")]) | ||||
|         } | ||||
| 
 | ||||
| 
 | ||||
|         let path: string = undefined | ||||
|         if (existsSync(this._imageDirectory + "/" + imageHash + ".jpg")) { | ||||
|             path = this._imageDirectory + "/" + imageHash + ".jpg" | ||||
|  | @ -61,7 +74,8 @@ export class ImgurToPanoramax extends Script { | |||
|         if (!path) { | ||||
|             return undefined | ||||
|         } | ||||
|         const licensePath = this._licenseDirectory + "/" + v.replaceAll(/[^a-zA-Z0-9]/g, "_") + ".json" | ||||
|         const licensePath = | ||||
|             this._licenseDirectory + "/" + v.replaceAll(/[^a-zA-Z0-9]/g, "_") + ".json" | ||||
|         if (!existsSync(licensePath)) { | ||||
|             return undefined | ||||
|         } | ||||
|  | @ -74,37 +88,45 @@ export class ImgurToPanoramax extends Script { | |||
|         const sequence = this.sequenceIds[license] | ||||
|         const author = licenseText.artist | ||||
| 
 | ||||
|         const handle = await open(path) | ||||
| 
 | ||||
|         const handle = await open(path); | ||||
| 
 | ||||
|         const stat = await handle.stat(); | ||||
|         const stat = await handle.stat() | ||||
| 
 | ||||
|         class MyFile extends File { | ||||
|             // we should set correct size
 | ||||
|             // otherwise we will encounter UND_ERR_REQ_CONTENT_LENGTH_MISMATCH
 | ||||
|             size = stat.size; | ||||
|             size = stat.size | ||||
|             stream = undefined | ||||
|         } | ||||
| 
 | ||||
|         const file = new MyFile([], path) | ||||
| 
 | ||||
|         file.stream = function() { | ||||
|             return handle.readableWebStream(); | ||||
|         }; | ||||
|             return handle.readableWebStream() | ||||
|         } | ||||
| 
 | ||||
|         console.log("Uploading", imageHash, sequence) | ||||
|         const result = await this.panoramax.uploadImage(<any> file, GeoOperations.centerpointCoordinates(feat), author, true, sequence) | ||||
|         const result = await this.panoramax.uploadImage( | ||||
|             <any>file, | ||||
|             GeoOperations.centerpointCoordinates(feat), | ||||
|             author, | ||||
|             true, | ||||
|             sequence, | ||||
|         ) | ||||
|         this.alreadyUploaded[imageHash] = result.value | ||||
|         await handle.close() | ||||
|         return new And([new Tag(key.replace("image", result.key), result.value), | ||||
|             new Tag(key,"")]) | ||||
|         return new And([new Tag(key.replace("image", result.key), result.value), new Tag(key, "")]) | ||||
|     } | ||||
| 
 | ||||
|     async main(args: string[]): Promise<void> { | ||||
|         this._imageDirectory = args[0] ?? "/home/pietervdvn/data/imgur-image-backup" | ||||
|         this._licenseDirectory = args[1] ?? "/home/pietervdvn/git/MapComplete-data/ImageLicenseInfo" | ||||
| 
 | ||||
|         const bounds = new BBox([[3.6984301050112833, 51.06715570450848], [3.7434328399847914, 51.039379568816145]]) | ||||
|         const maxcount = 100 | ||||
|         const bounds = new BBox([ | ||||
|             [3.6984301050112833, 51.06715570450848], | ||||
|             [3.7434328399847914, 51.039379568816145], | ||||
|         ]) | ||||
|         const maxcount = 500 | ||||
|         const filter = new RegexTag("image", /^https:\/\/i.imgur.com\/.*/) | ||||
|         const overpass = new Overpass(filter, [], Constants.defaultOverpassUrls[0]) | ||||
|         const features = (await overpass.queryGeoJson(bounds))[0].features | ||||
|  | @ -124,33 +146,39 @@ export class ImgurToPanoramax extends Script { | |||
|             for (const k of ["image", "image:menu", "image:streetsign"]) { | ||||
|                 changedTags.push(await this.uploadImage(k, f, sequences)) | ||||
|                 for (let i = 0; i < 20; i++) { | ||||
|                     changedTags.push( | ||||
|                         await this.uploadImage(k + ":" + i, f, sequences), | ||||
|                     ) | ||||
|                     changedTags.push(await this.uploadImage(k + ":" + i, f, sequences)) | ||||
|                 } | ||||
|             } | ||||
|             const action = new ChangeTagAction(f.properties.id, new And(Utils.NoNull(changedTags)), | ||||
|                 f.properties, { | ||||
|             const action = new ChangeTagAction( | ||||
|                 f.properties.id, | ||||
|                 new And(Utils.NoNull(changedTags)), | ||||
|                 f.properties, | ||||
|                 { | ||||
|                     theme: "image-mover", | ||||
|                     changeType: "link-image", | ||||
|                 }, | ||||
|             ) | ||||
|             changes.push(...await action.CreateChangeDescriptions()) | ||||
|             changes.push(...(await action.CreateChangeDescriptions())) | ||||
|             converted++ | ||||
|         } while (converted < maxcount) | ||||
| 
 | ||||
|         const modif: string[] = Utils.Dedup(changes.map(ch => ch.type + "/" + ch.id)) | ||||
|         const modifiedObjectsFresh = | ||||
|           <OsmObject[]>  (await Promise.all(modif.map(id => new OsmObjectDownloader().DownloadObjectAsync(id)))) | ||||
|                 .filter(m => m !== "deleted") | ||||
|         const modif: string[] = Utils.Dedup(changes.map((ch) => ch.type + "/" + ch.id)) | ||||
|         const modifiedObjectsFresh = <OsmObject[]>( | ||||
|             ( | ||||
|                 await Promise.all( | ||||
|                     modif.map((id) => new OsmObjectDownloader().DownloadObjectAsync(id)), | ||||
|                 ) | ||||
|             ).filter((m) => m !== "deleted") | ||||
|         ) | ||||
|         const modifiedObjects = Changes.createChangesetObjectsStatic( | ||||
|             changes, | ||||
|             modifiedObjectsFresh,false, []) | ||||
|             modifiedObjectsFresh, | ||||
|             false, | ||||
|             [], | ||||
|         ) | ||||
|         const cs = Changes.buildChangesetXML("0", modifiedObjects) | ||||
|         writeFileSync("imgur_to_panoramax.osc", cs, "utf8") | ||||
| 
 | ||||
|     } | ||||
| 
 | ||||
| } | ||||
| 
 | ||||
| new ImgurToPanoramax().run() | ||||
|  |  | |||
|  | @ -10,16 +10,19 @@ import ScriptUtils from "./ScriptUtils" | |||
| import { Utils } from "../src/Utils" | ||||
| import SpecialVisualizations from "../src/UI/SpecialVisualizations" | ||||
| import Constants from "../src/Models/Constants" | ||||
| import { AvailableRasterLayers, RasterLayerPolygon } from "../src/Models/RasterLayers" | ||||
| import { AvailableRasterLayers, EditorLayerIndexProperties, RasterLayerPolygon } from "../src/Models/RasterLayers" | ||||
| import { ImmutableStore } from "../src/Logic/UIEventSource" | ||||
| import * as eli from "../public/assets/data/editor-layer-index.json" | ||||
| import * as eli_global from "../src/assets/global-raster-layers.json" | ||||
| import * as layers_global from "../src/assets/global-raster-layers.json" | ||||
| import eli_global from "../src/assets/generated/editor-layer-index-global.json" | ||||
| import bing from "../src/assets/bing.json" | ||||
| 
 | ||||
| import ValidationUtils from "../src/Models/ThemeConfig/Conversion/ValidationUtils" | ||||
| import { LayerConfigJson } from "../src/Models/ThemeConfig/Json/LayerConfigJson" | ||||
| import { QuestionableTagRenderingConfigJson } from "../src/Models/ThemeConfig/Json/QuestionableTagRenderingConfigJson" | ||||
| import Script from "./Script" | ||||
| import crypto from "crypto" | ||||
| 
 | ||||
| import { RasterLayerProperties } from "../src/Models/RasterLayerProperties" | ||||
| const sharp = require("sharp") | ||||
| 
 | ||||
| class GenerateLayouts extends Script { | ||||
|  | @ -264,10 +267,12 @@ class GenerateLayouts extends Script { | |||
|         } | ||||
|         const urls: string[] = [] | ||||
|         const regex = /{switch:([^}]+)}/ | ||||
|         const rasterLayers = [ | ||||
|         const rasterLayers: {properties: RasterLayerProperties}[] = [ | ||||
|             AvailableRasterLayers.defaultBackgroundLayer, | ||||
|             ...eli.features, | ||||
|             ...eli_global.layers.map((properties) => ({ properties })), | ||||
|              bing, | ||||
|             ...eli_global.map((properties) => ({ properties })), | ||||
|             ...layers_global.layers.map((properties) => ({ properties })), | ||||
|         ] | ||||
|         for (const feature of rasterLayers) { | ||||
|             const f = <RasterLayerPolygon>feature | ||||
|  |  | |||
|  | @ -65,9 +65,11 @@ class TileCountServer extends Script { | |||
|                     const layers = await tcs.getLayers() | ||||
|                     const meta = await tcs.getMeta() | ||||
|                     const mostSuitable = await tcs.findSuitableDatabases() | ||||
|                     return JSON.stringify({ meta, | ||||
|                     return JSON.stringify({ | ||||
|                         meta, | ||||
|                         suitableDatabases: mostSuitable, | ||||
|                         layers: Array.from(layers) }) | ||||
|                         layers: Array.from(layers), | ||||
|                     }) | ||||
|                 }, | ||||
|             }, | ||||
|             { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue