forked from MapComplete/MapComplete
Add polygon merging
This commit is contained in:
parent
ee38cdb9d7
commit
ee3e000cd1
11 changed files with 460 additions and 305 deletions
|
@ -5,91 +5,57 @@ import Script from "../Script"
|
|||
import fs from "fs"
|
||||
import { Or } from "../../src/Logic/Tags/Or"
|
||||
import { RegexTag } from "../../src/Logic/Tags/RegexTag"
|
||||
import { Utils } from "../../src/Utils"
|
||||
import { ValidateThemeEnsemble } from "../../src/Models/ThemeConfig/Conversion/Validation"
|
||||
import { AllKnownLayouts } from "../../src/Customizations/AllKnownLayouts"
|
||||
|
||||
class LuaSnippets {
|
||||
/**
|
||||
* The main piece of code that calls `process_poi`
|
||||
*/
|
||||
static tail = [
|
||||
"function osm2pgsql.process_node(object)",
|
||||
" process_poi(object, object:as_point())",
|
||||
|
||||
public static helpers = [
|
||||
"function countTbl(tbl)\n" +
|
||||
" local c = 0\n" +
|
||||
" for n in pairs(tbl) do \n" +
|
||||
" c = c + 1 \n" +
|
||||
" end\n" +
|
||||
" return c\n" +
|
||||
"end",
|
||||
"",
|
||||
"function osm2pgsql.process_way(object)",
|
||||
" if object.is_closed then",
|
||||
" process_poi(object, object:as_polygon():centroid())",
|
||||
" end",
|
||||
"end",
|
||||
""].join("\n")
|
||||
].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 _id: string
|
||||
private readonly _tags: TagsFilter
|
||||
private readonly _foundInThemes: string[]
|
||||
|
||||
constructor(id: string, tags: TagsFilter, foundInThemes: string[] = []) {
|
||||
this._tags = tags
|
||||
this._id = id
|
||||
this._foundInThemes = foundInThemes
|
||||
}
|
||||
|
||||
public functionName() {
|
||||
if (!this._tags) {
|
||||
return undefined
|
||||
public static toLuaFilter(tag: TagsFilter, useParens: boolean = false): string {
|
||||
if (tag instanceof Tag) {
|
||||
return `object.tags["${tag.key}"] == "${tag.value}"`
|
||||
}
|
||||
return `process_poi_${this._id}`
|
||||
}
|
||||
|
||||
public generateFunction(): string {
|
||||
if (!this._tags) {
|
||||
return undefined
|
||||
if (tag instanceof And) {
|
||||
const expr = tag.and.map(t => this.toLuaFilter(t, true)).join(" and ")
|
||||
if (useParens) {
|
||||
return "(" + expr + ")"
|
||||
}
|
||||
return expr
|
||||
}
|
||||
return [
|
||||
`local pois_${this._id} = osm2pgsql.define_table({`,
|
||||
this._foundInThemes ? "-- used in themes: " + this._foundInThemes.join(", ") : "",
|
||||
` name = '${this._id}',`,
|
||||
" ids = { type = 'any', type_column = 'osm_type', id_column = 'osm_id' },",
|
||||
" columns = {",
|
||||
" { column = 'tags', type = 'jsonb' },",
|
||||
" { column = 'geom', type = 'point', projection = 4326, not_null = true },",
|
||||
" }" +
|
||||
"})",
|
||||
"",
|
||||
"",
|
||||
`function ${this.functionName()}(object, geom)`,
|
||||
" local matches_filter = " + this.toLuaFilter(this._tags),
|
||||
" if( not matches_filter) then",
|
||||
" return",
|
||||
" end",
|
||||
" local a = {",
|
||||
" geom = geom,",
|
||||
" tags = object.tags",
|
||||
" }",
|
||||
" ",
|
||||
` pois_${this._id}:insert(a)`,
|
||||
"end",
|
||||
"",
|
||||
].join("\n")
|
||||
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) {
|
||||
let expr = LuaSnippets.regexTagToLua(tag)
|
||||
if (useParens) {
|
||||
expr = "(" + expr + ")"
|
||||
}
|
||||
return expr
|
||||
}
|
||||
let msg = "Could not handle" + tag.asHumanString(false, false, {})
|
||||
console.error(msg)
|
||||
throw msg
|
||||
}
|
||||
|
||||
private regexTagToLua(tag: RegexTag) {
|
||||
private static regexTagToLua(tag: RegexTag) {
|
||||
if (typeof tag.value === "string" && tag.invert) {
|
||||
return `object.tags["${tag.key}"] ~= "${tag.value}"`
|
||||
}
|
||||
|
||||
const v = (<RegExp> tag.value).source.replace(/\\\//g, "/")
|
||||
const v = (<RegExp>tag.value).source.replace(/\\\//g, "/")
|
||||
|
||||
if ("" + tag.value === "/.+/is" && !tag.invert) {
|
||||
return `object.tags["${tag.key}"] ~= nil`
|
||||
|
@ -115,35 +81,58 @@ class GenerateLayerLua {
|
|||
return `(object.tags["${tag.key}"] ~= nil and string.find(object.tags["${tag.key}"], "${v}"))`
|
||||
}
|
||||
|
||||
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) {
|
||||
let expr = this.regexTagToLua(tag)
|
||||
if (useParens) {
|
||||
expr = "(" + expr + ")"
|
||||
}
|
||||
return expr
|
||||
}
|
||||
let msg = "Could not handle" + tag.asHumanString(false, false, {})
|
||||
console.error(msg)
|
||||
throw msg
|
||||
}
|
||||
|
||||
class GenerateLayerLua {
|
||||
private readonly _id: string
|
||||
private readonly _tags: TagsFilter
|
||||
private readonly _foundInThemes: string[]
|
||||
|
||||
constructor(id: string, tags: TagsFilter, foundInThemes: string[] = []) {
|
||||
this._tags = tags
|
||||
this._id = id
|
||||
this._foundInThemes = foundInThemes
|
||||
}
|
||||
|
||||
public generateTables(): string {
|
||||
if (!this._tags) {
|
||||
return undefined
|
||||
}
|
||||
return [
|
||||
`db_tables.pois_${this._id} = osm2pgsql.define_table({`,
|
||||
this._foundInThemes ? "-- used in themes: " + this._foundInThemes.join(", ") : "",
|
||||
` name = 'pois_${this._id}',`,
|
||||
" ids = { type = 'any', type_column = 'osm_type', id_column = 'osm_id' },",
|
||||
" columns = {",
|
||||
" { column = 'tags', type = 'jsonb' },",
|
||||
" { column = 'geom', type = 'point', projection = 4326, not_null = true },",
|
||||
" }",
|
||||
"})",
|
||||
"",
|
||||
`db_tables.lines_${this._id} = osm2pgsql.define_table({`,
|
||||
this._foundInThemes ? "-- used in themes: " + this._foundInThemes.join(", ") : "",
|
||||
` name = 'lines_${this._id}',`,
|
||||
" ids = { type = 'any', type_column = 'osm_type', id_column = 'osm_id' },",
|
||||
" columns = {",
|
||||
" { column = 'tags', type = 'jsonb' },",
|
||||
" { column = 'geom', type = 'linestring', projection = 4326, not_null = true },",
|
||||
" }",
|
||||
"})",
|
||||
|
||||
`db_tables.polygons_${this._id} = osm2pgsql.define_table({`,
|
||||
this._foundInThemes ? "-- used in themes: " + this._foundInThemes.join(", ") : "",
|
||||
` name = 'polygons_${this._id}',`,
|
||||
" ids = { type = 'any', type_column = 'osm_type', id_column = 'osm_id' },",
|
||||
" columns = {",
|
||||
" { column = 'tags', type = 'jsonb' },",
|
||||
" { column = 'geom', type = 'polygon', projection = 4326, not_null = true },",
|
||||
" }",
|
||||
"})",
|
||||
"",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
class GenerateBuildDbScript extends Script {
|
||||
|
@ -163,14 +152,93 @@ class GenerateBuildDbScript extends Script {
|
|||
})
|
||||
|
||||
const script = [
|
||||
...generators.map(g => g.generateFunction()),
|
||||
LuaSnippets.combine(Utils.NoNull(generators.map(g => g.functionName()))),
|
||||
LuaSnippets.tail,
|
||||
"local db_tables = {}",
|
||||
LuaSnippets.helpers,
|
||||
...generators.map(g => g.generateTables()),
|
||||
this.generateProcessPoi(allNeededLayers),
|
||||
this.generateProcessWay(allNeededLayers),
|
||||
].join("\n\n\n")
|
||||
const path = "build_db.lua"
|
||||
fs.writeFileSync(path, script, "utf-8")
|
||||
console.log("Written", path)
|
||||
console.log(allNeededLayers.size+" layers will be created. Make sure to set 'max_connections' to at least "+(10 + allNeededLayers.size) )
|
||||
console.log(allNeededLayers.size + " layers will be created with 3 tables each. Make sure to set 'max_connections' to at least " + (10 + 3 * allNeededLayers.size))
|
||||
}
|
||||
|
||||
private earlyAbort() {
|
||||
return [" if countTbl(object.tags) == 0 then",
|
||||
" return",
|
||||
" end",
|
||||
""].join("\n")
|
||||
}
|
||||
|
||||
private generateProcessPoi(allNeededLayers: Map<string, { tags: TagsFilter; foundInTheme: string[] }>) {
|
||||
const body: string[] = []
|
||||
allNeededLayers.forEach(({ tags }, layerId) => {
|
||||
body.push(
|
||||
this.insertInto(tags, layerId, "pois_").join("\n"),
|
||||
)
|
||||
})
|
||||
|
||||
return [
|
||||
"function osm2pgsql.process_node(object)",
|
||||
this.earlyAbort(),
|
||||
" local geom = object:as_point()",
|
||||
" local matches_filter = false",
|
||||
body.join("\n"),
|
||||
"end",
|
||||
].join("\n")
|
||||
}
|
||||
|
||||
/**
|
||||
* If matches_filter
|
||||
* @param tags
|
||||
* @param layerId
|
||||
* @param tableprefix
|
||||
* @private
|
||||
*/
|
||||
private insertInto(tags: TagsFilter, layerId: string, tableprefix: "pois_" | "lines_" | "polygons_") {
|
||||
const filter = LuaSnippets.toLuaFilter(tags)
|
||||
return [
|
||||
" matches_filter = " + filter,
|
||||
" if matches_filter then",
|
||||
" db_tables." + tableprefix + layerId + ":insert({",
|
||||
" geom = geom,",
|
||||
" tags = object.tags",
|
||||
" })",
|
||||
" end",
|
||||
]
|
||||
}
|
||||
|
||||
private generateProcessWay(allNeededLayers: Map<string, { tags: TagsFilter }>) {
|
||||
const bodyLines: string[] = []
|
||||
allNeededLayers.forEach(({ tags }, layerId) => {
|
||||
bodyLines.push(this.insertInto(tags, layerId, "lines_").join("\n"))
|
||||
})
|
||||
|
||||
const bodyPolygons: string[] = []
|
||||
allNeededLayers.forEach(({ tags }, layerId) => {
|
||||
bodyPolygons.push(this.insertInto(tags, layerId, "polygons_").join("\n"))
|
||||
})
|
||||
|
||||
return [
|
||||
"function process_polygon(object, geom)",
|
||||
" local matches_filter",
|
||||
...bodyPolygons,
|
||||
"end",
|
||||
"function process_linestring(object, geom)",
|
||||
" local matches_filter",
|
||||
...bodyLines,
|
||||
"end",
|
||||
"",
|
||||
"function osm2pgsql.process_way(object)",
|
||||
this.earlyAbort(),
|
||||
" if object.is_closed then",
|
||||
" process_polygon(object, object:as_polygon())",
|
||||
" else",
|
||||
" process_linestring(object, object:as_linestring())",
|
||||
" end",
|
||||
"end",
|
||||
].join("\n")
|
||||
}
|
||||
}
|
||||
|
||||
|
|
Loading…
Add table
Add a link
Reference in a new issue