forked from MapComplete/MapComplete
		
	Layerserver: improve docs, add stub of script that generates configuration file
This commit is contained in:
		
							parent
							
								
									c98891d4bd
								
							
						
					
					
						commit
						fb088059a5
					
				
					 3 changed files with 194 additions and 5 deletions
				
			
		| 
						 | 
					@ -1,11 +1,44 @@
 | 
				
			||||||
sudo docker run --name some-postgis -e POSTGRES_PASSWORD=none -e POSTGRES_USER=user -d -p 5444:5432 -v /home/pietervdvn/data/pgsql/:/var/lib/postgresql/data postgis/postgis
 | 
					# Setting up a synced OSM-server for quick layer access
 | 
				
			||||||
 | 
					
 | 
				
			||||||
-> Via PGAdmin een database maken en:
 | 
					## Setting up the SQL-server:
 | 
				
			||||||
1) Postgis activeren (rechtsklikken > Create > extension)
 | 
					 | 
				
			||||||
2) HStore activeren
 | 
					 | 
				
			||||||
 | 
					
 | 
				
			||||||
Installeer osm2pgsql (hint: compile from source is painless)
 | 
					`sudo docker run --name some-postgis -e POSTGRES_PASSWORD=password -e POSTGRES_USER=user -d -p 5444:5432 -v /home/pietervdvn/data/pgsql/:/var/lib/postgresql/data postgis/postgis`
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Then, connect to this databank with PGAdmin, create a database within it.
 | 
				
			||||||
 | 
					Then activate following extensions for this database (right click > Create > Extension):
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					- Postgis activeren (rechtsklikken > Create > extension)
 | 
				
			||||||
 | 
					- HStore activeren
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Install osm2pgsql (hint: compile from source is painless)
 | 
				
			||||||
 | 
					
 | 
				
			||||||
pg_tileserv kan hier gedownload worden: https://github.com/CrunchyData/pg_tileserv
 | 
					pg_tileserv kan hier gedownload worden: https://github.com/CrunchyData/pg_tileserv
 | 
				
			||||||
 | 
					
 | 
				
			||||||
DATABASE_URL=postgresql://user:none@localhost:5444/osm-poi ./pg_tileserv 
 | 
					DATABASE_URL=postgresql://user:none@localhost:5444/osm-poi ./pg_tileserv 
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Create export scripts for every layer
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Use scripts/osm2pgsl
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Importing data
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					To seed the database:
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
 | 
					osm2pgsql -O flex -S drinking_water.lua -s  --flat-nodes=import-help-file -d postgresql://user:none@localhost:5444/osm-poi andorra-latest.osm.pbf 
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					## Deploying a tile server
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
 | 
					export DATABASE_URL=postgresql://user:none@localhost:5444/osm-poi
 | 
				
			||||||
 | 
					./pg_tileserv
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					Tiles are available at: 
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
 | 
					map.addSource("drinking_water", {
 | 
				
			||||||
 | 
					"type": "vector",
 | 
				
			||||||
 | 
					"tiles": ["http://127.0.0.2:7800/public.drinking_water/{z}/{x}/{y}.pbf"] // http://127.0.0.2:7800/public.drinking_water.json",
 | 
				
			||||||
 | 
					})
 | 
				
			||||||
 | 
					````
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
							
								
								
									
										136
									
								
								scripts/osm2pgsql/generateLayerFile.ts
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										136
									
								
								scripts/osm2pgsql/generateLayerFile.ts
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
					@ -0,0 +1,136 @@
 | 
				
			||||||
 | 
					import LayerConfig from "../../src/Models/ThemeConfig/LayerConfig"
 | 
				
			||||||
 | 
					import { TagsFilter } from "../../src/Logic/Tags/TagsFilter"
 | 
				
			||||||
 | 
					import { Tag } from "../../src/Logic/Tags/Tag"
 | 
				
			||||||
 | 
					import { And } from "../../src/Logic/Tags/And"
 | 
				
			||||||
 | 
					import Script from "../Script"
 | 
				
			||||||
 | 
					import { AllSharedLayers } from "../../src/Customizations/AllSharedLayers"
 | 
				
			||||||
 | 
					import fs from "fs"
 | 
				
			||||||
 | 
					import { Or } from "../../src/Logic/Tags/Or"
 | 
				
			||||||
 | 
					import { RegexTag } from "../../src/Logic/Tags/RegexTag"
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class LuaSnippets{
 | 
				
			||||||
 | 
					    /**
 | 
				
			||||||
 | 
					     * The main piece of code that calls `process_poi`
 | 
				
			||||||
 | 
					     */
 | 
				
			||||||
 | 
					    static tail = [
 | 
				
			||||||
 | 
					        "function osm2pgsql.process_node(object)",
 | 
				
			||||||
 | 
					        "  process_poi(object, object:as_point())",
 | 
				
			||||||
 | 
					        "end",
 | 
				
			||||||
 | 
					        "",
 | 
				
			||||||
 | 
					        "function osm2pgsql.process_way(object)",
 | 
				
			||||||
 | 
					        "  if object.is_closed then",
 | 
				
			||||||
 | 
					        "    process_poi(object, object:as_polygon():centroid())",
 | 
				
			||||||
 | 
					        "  end",
 | 
				
			||||||
 | 
					        "end",
 | 
				
			||||||
 | 
					        ""].join("\n")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public static combine(calls: string[]): string{
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            `function process_poi(object, geom)`,
 | 
				
			||||||
 | 
					            ...calls.map(c => "  "+c+"(object, geom)"),
 | 
				
			||||||
 | 
					            `end`,
 | 
				
			||||||
 | 
					        ].join("\n")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					class GenerateLayerLua {
 | 
				
			||||||
 | 
					    private readonly _layer: LayerConfig
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    constructor(layer: LayerConfig) {
 | 
				
			||||||
 | 
					        this._layer = layer
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					    public functionName(){
 | 
				
			||||||
 | 
					        const l = this._layer
 | 
				
			||||||
 | 
					        return `process_poi_${l.id}`
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    public generateFunction(): string {
 | 
				
			||||||
 | 
					        const l = this._layer
 | 
				
			||||||
 | 
					        return [
 | 
				
			||||||
 | 
					            `local pois_${l.id} = osm2pgsql.define_table({`,
 | 
				
			||||||
 | 
					            `  name = '${l.id}',`,
 | 
				
			||||||
 | 
					            "  ids = { type = 'any', type_column = 'osm_type', id_column = 'osm_id' },",
 | 
				
			||||||
 | 
					            "  columns = {",
 | 
				
			||||||
 | 
					            "    { column = 'tags', type = 'jsonb' },",
 | 
				
			||||||
 | 
					            "    { column = 'geom', type = 'point', not_null = true },",
 | 
				
			||||||
 | 
					            "  }" +
 | 
				
			||||||
 | 
					            "})",
 | 
				
			||||||
 | 
					            "",
 | 
				
			||||||
 | 
					            "",
 | 
				
			||||||
 | 
					            `function ${this.functionName()}(object, geom)`,
 | 
				
			||||||
 | 
					            "  local matches_filter = " + this.toLuaFilter(l.source.osmTags),
 | 
				
			||||||
 | 
					            "  if( not matches_filter) then",
 | 
				
			||||||
 | 
					            "    return",
 | 
				
			||||||
 | 
					            "  end",
 | 
				
			||||||
 | 
					            "  local a = {",
 | 
				
			||||||
 | 
					            "    geom = geom,",
 | 
				
			||||||
 | 
					            "    tags = object.tags",
 | 
				
			||||||
 | 
					            "  }",
 | 
				
			||||||
 | 
					            "  ",
 | 
				
			||||||
 | 
					            `  pois_${l.id}:insert(a)`,
 | 
				
			||||||
 | 
					            "end",
 | 
				
			||||||
 | 
					            ""
 | 
				
			||||||
 | 
					        ].join("\n")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    private toLuaFilter(tag: TagsFilter, useParens: boolean = false): string {
 | 
				
			||||||
 | 
					        if (tag instanceof Tag) {
 | 
				
			||||||
 | 
					            return `object.tags["${tag.key}"] == "${tag.value}"`
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (tag instanceof And) {
 | 
				
			||||||
 | 
					            const expr = tag.and.map(t => this.toLuaFilter(t, true)).join(" and ")
 | 
				
			||||||
 | 
					            if (useParens) {
 | 
				
			||||||
 | 
					                return "(" + expr + ")"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return expr
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (tag instanceof Or) {
 | 
				
			||||||
 | 
					            const expr = tag.or.map(t => this.toLuaFilter(t, true)).join(" or ")
 | 
				
			||||||
 | 
					            if (useParens) {
 | 
				
			||||||
 | 
					                return "(" + expr + ")"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return expr
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        if (tag instanceof RegexTag) {
 | 
				
			||||||
 | 
					            if(typeof tag.value === "string" && tag.invert){
 | 
				
			||||||
 | 
					                return `object.tags["${tag.key}"] ~= "${tag.value}"`
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					            let expr = `not string.find(object.tags["${tag.key}"], "${tag.value}")`
 | 
				
			||||||
 | 
					            if (!tag.invert) {
 | 
				
			||||||
 | 
					                expr = "not " + expr
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            if (useParens) {
 | 
				
			||||||
 | 
					                expr = "(" + expr + ")"
 | 
				
			||||||
 | 
					            }
 | 
				
			||||||
 | 
					            return expr
 | 
				
			||||||
 | 
					        }
 | 
				
			||||||
 | 
					        let msg = "Could not handle" + tag.asHumanString(false, false, {})
 | 
				
			||||||
 | 
					        console.error(msg)
 | 
				
			||||||
 | 
					        throw msg
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					class GenerateLayerFile extends Script {
 | 
				
			||||||
 | 
					    constructor() {
 | 
				
			||||||
 | 
					        super("Generates a .lua-file to use with osm2pgsql")
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					    async main(args: string[]) {
 | 
				
			||||||
 | 
					        let dw = AllSharedLayers.sharedLayers.get("drinking_water")
 | 
				
			||||||
 | 
					        let t = AllSharedLayers.sharedLayers.get("toilet")
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const generators = [dw, t].map(l => new GenerateLayerLua(l))
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        const script = [
 | 
				
			||||||
 | 
					            ...generators.map(g => g.generateFunction()),
 | 
				
			||||||
 | 
					            LuaSnippets.combine(generators.map(g => g.functionName())),
 | 
				
			||||||
 | 
					            LuaSnippets.tail
 | 
				
			||||||
 | 
					        ].join("\n\n\n")
 | 
				
			||||||
 | 
					        const path = "build_db.lua"
 | 
				
			||||||
 | 
					        fs.writeFileSync(path,script, "utf-8")
 | 
				
			||||||
 | 
					        console.log("Written", path)
 | 
				
			||||||
 | 
					    }
 | 
				
			||||||
 | 
					}
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					new GenerateLayerFile().run()
 | 
				
			||||||
| 
						 | 
					@ -36,6 +36,26 @@
 | 
				
			||||||
        },
 | 
					        },
 | 
				
			||||||
      )
 | 
					      )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        map.addSource("toilet", {
 | 
				
			||||||
 | 
					            "type": "vector",
 | 
				
			||||||
 | 
					            "tiles": ["http://127.0.0.2:7800/public.toilet/{z}/{x}/{y}.pbf"] // http://127.0.0.2:7800/public.drinking_water.json",
 | 
				
			||||||
 | 
					        })
 | 
				
			||||||
 | 
					
 | 
				
			||||||
 | 
					        map.addLayer(
 | 
				
			||||||
 | 
					            {
 | 
				
			||||||
 | 
					                "id": "toilet_layer",
 | 
				
			||||||
 | 
					                "type": "circle",
 | 
				
			||||||
 | 
					                "source": "toilet",
 | 
				
			||||||
 | 
					                "source-layer": "public.toilet",
 | 
				
			||||||
 | 
					                "paint": {
 | 
				
			||||||
 | 
					                    "circle-radius": 5,
 | 
				
			||||||
 | 
					                    "circle-color": "#0000ff",
 | 
				
			||||||
 | 
					                    "circle-stroke-width": 2,
 | 
				
			||||||
 | 
					                    "circle-stroke-color": "#000000",
 | 
				
			||||||
 | 
					                },
 | 
				
			||||||
 | 
					            },
 | 
				
			||||||
 | 
					        )
 | 
				
			||||||
 | 
					
 | 
				
			||||||
      map.on('click', 'drinking_water_layer', (e) => {
 | 
					      map.on('click', 'drinking_water_layer', (e) => {
 | 
				
			||||||
// Copy coordinates array.
 | 
					// Copy coordinates array.
 | 
				
			||||||
        console.log(e)
 | 
					        console.log(e)
 | 
				
			||||||
| 
						 | 
					
 | 
				
			||||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue