From eb1b52100cc054f7ddbeb865e8b001828b07704d Mon Sep 17 00:00:00 2001 From: Tor Andersson Date: Sun, 17 Mar 2024 14:01:52 +0100 Subject: Parse layout and generate map data. --- tools/layout.svg | 7086 +++++++++++++++++++++++++------------------------ tools/names.txt | 2 +- tools/parse-layout.js | 235 +- 3 files changed, 3783 insertions(+), 3540 deletions(-) (limited to 'tools') diff --git a/tools/layout.svg b/tools/layout.svg index a0c043e..20c77f0 100644 --- a/tools/layout.svg +++ b/tools/layout.svg @@ -40,10 +40,10 @@ inkscape:window-height="480" id="namedview6" showgrid="false" - inkscape:zoom="0.96460962" - inkscape:cx="1030.3441" - inkscape:cy="834.95823" - inkscape:current-layer="svg4" + inkscape:zoom="2.9584691" + inkscape:cx="719.82834" + inkscape:cy="902.87542" + inkscape:current-layer="g5174" inkscape:document-rotation="0" showguides="false"> + image-rendering="pixelated" + height="1654" + width="2485" + y="0" + x="0" + style="display:inline" /> - - - - - - - - - - - - - - - - - + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2422" + cx="78.936989" + cy="730.62244" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2424" + cx="201.31735" + cy="1418.5251" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2426" + cx="482.35126" + cy="1155.5575" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2428" + cx="595.6712" + cy="312.47647" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2430" + cx="861.29175" + cy="190.86034" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2432" + cx="1175.3353" + cy="300.33441" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2434" + cx="1445.4271" + cy="209.21451" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2436" + cx="1509.8654" + cy="581.40253" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2438" + cx="1640.8955" + cy="840.84808" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2440" + cx="2050.6885" + cy="1055.5642" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2442" + cx="2075.1187" + cy="528.09021" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2444" + cx="2006.139" + cy="1327.3361" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2446" + cx="1627.3788" + cy="1320.0774" + r="16" /> + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2448" + cx="1184.2834" + cy="1330.5629" + r="16" /> - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - + style="fill:#ffffff;fill-opacity:0.809893;stroke:none" + id="circle2450" + cx="245.14282" + cy="937.73083" + r="16" /> + style="fill:#ff2f2f;fill-opacity:0.54878;stroke:none;stroke-opacity:1" + id="circle846" + cx="1340.0817" + cy="75.316978" + r="7" /> + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle797" + cx="766.43317" + cy="555.50574" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle799" + cx="807.36475" + cy="588.40314" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle801" + cx="873.23419" + cy="575.15051" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle803" + cx="911.86981" + cy="594.45319" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle805" + cx="958.63812" + cy="545.00159" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle807" + cx="912.4707" + cy="504.22742" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle809" + cx="860.4256" + cy="490.43265" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle811" + cx="813.49341" + cy="464.85056" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle813" + cx="960.49445" + cy="457.91592" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle815" + cx="908.10431" + cy="440.11957" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle817" + cx="939.33179" + cy="390.99731" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle819" + cx="831.24127" + cy="402.03555" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle821" + cx="813.12036" + cy="355.13828" + r="7" /> + style="fill:#ff2f2f;fill-opacity:0.54878" + id="circle823" + cx="755.78412" + cy="396.97943" + r="7" /> + + + + + + + + + + + + style="display:inline"> Trietr + y="987.9718" + id="tspan3040">Trier + style="display:none;fill:#ff2a2a"> + inkscape:label="$DIAMONDS" + style="display:none"> + inkscape:label="$SPADES" + style="display:none"> + inkscape:label="$CLUBS" + style="display:none"> + style="display:none"> + inkscape:label="$Netherlands" + style="display:none"> + inkscape:label="$Prussia" + style="display:none"> + inkscape:label="$Poland" + style="display:none"> - + inkscape:label="$Silesia" + style="display:none"> + + inkscape:label="$Saxony" + style="display:none"> + inkscape:label="$Bavaria" + style="display:none"> + inkscape:label="$Austria_E" + style="display:none"> + + inkscape:label="$HRE_E" + style="display:none"> + + + inkscape:label="$HRE_W" + sodipodi:insensitive="true" + style="display:none"> Wiltz -Trietr +Trier Saarlouis diff --git a/tools/parse-layout.js b/tools/parse-layout.js index 5219705..e3a76fd 100644 --- a/tools/parse-layout.js +++ b/tools/parse-layout.js @@ -2,7 +2,7 @@ const fs = require("fs") let points = {} let rects = {} -let edges = [] +let edges = {} let mode, name, x, y, w, h, cx, cy, rx, ry, x2, y2 function add_point(x, y) { @@ -19,9 +19,16 @@ function add_rect(x, y, w, h) { rects[name] = [ [x,y,x+w,y+h] ] } +function add_edge(x1, y1, x2, y2) { + if (name in edges) + edges[name].push({x1,y1,x2,y2}) + else + edges[name] = [ {x1,y1,x2,y2} ] +} + function flush() { if (mode === 'path') { - edges.push([ x, y, x2, y2 ]) + add_edge(x, y, x2, y2) } if (mode === 'rect') { if (name.startsWith("$")) @@ -180,6 +187,21 @@ function find_closest_node(list, x, y) { return [ nn, nd ] } +function find_closest_city(x, y) { + let nd = Infinity, nn = -1 + + for (let i = 0; i < cities.length; ++i) { + let n = cities[i] + let d = Math.hypot(n.x - x, n.y - y) + if (d < nd) { + nd = d + nn = i + } + } + + return nn +} + function find_enclosing_rect(list, x, y) { for (let [x1, y1, x2, y2] of list) { if (x >= x1 && x <= x2) @@ -189,36 +211,225 @@ function find_enclosing_rect(list, x, y) { return false } +const FLANDERS = "Flanders" +const BOHEMIA = "Bohemia" + +const CLUBS = "clubs" +const HEARTS = "hearts" +const SPADES = "spades" +const DIAMONDS = "diamonds" + +const FRANCE = "France" +const BAVARIA = "Bavaria" +const PRUSSIA = "Prussia" +const SAXONY = "Saxony" +const AUSTRIA = "Austria" +const AUSTRIAN_NETHERLANDS = "Austrian Netherlands" +const HRE = "Holy Roman Empire" +const NETHERLANDS = "Netherlands" +const SILESIA = "Silesia" +const POLAND = "Poland" + +const PRAGMATIC_ARMY = "Pragmatic Army" + // FIND and label all points! let all_labels = labels.slice() -let out = {} +let cities = [] for (let key in points) { - out = {} for (let [x, y] of points[key]) { let [ node, dist ] = find_closest_node(labels, x, y) if (dist > 10) { console.log(key,x,y, dist) } if (node) { - if (node.name in out) - console.log("DUPLICATE", node.name, x, y, out[node.name]) labels = labels.filter(x => x !== node) let suit = "UNKNOWN" + if (find_enclosing_rect(rects.$CLUBS, x, y)) - suit = "clubs" + suit = CLUBS else if (find_enclosing_rect(rects.$HEARTS, x, y)) - suit = "hearts" + suit = HEARTS else if (find_enclosing_rect(rects.$DIAMONDS, x, y)) - suit = "diamonds" + suit = DIAMONDS else if (find_enclosing_rect(rects.$SPADES, x, y)) - suit = "spades" + suit = SPADES else console.log("NOT ASSIGNED SUIT", x, y) - out[node.name] = [x, y, dist, suit] + + let map = "UNKNOWN" + let country = "UNKNOWN" + if (find_enclosing_rect(rects.$HRE_W, x, y)) { + map = FLANDERS + country = HRE + } + else if (find_enclosing_rect(rects.$HRE_E, x, y)) { + map = BOHEMIA + country = HRE + } + else if (find_enclosing_rect(rects.$Austria_W, x, y)) { + map = FLANDERS + country = AUSTRIA + } + else if (find_enclosing_rect(rects.$Austria_E, x, y)) { + map = BOHEMIA + country = AUSTRIA + } + else if (find_enclosing_rect(rects.$Bavaria, x, y)) { + map = BOHEMIA + country = BAVARIA + } + else if (find_enclosing_rect(rects.$Saxony, x, y)) { + map = BOHEMIA + country = SAXONY + } + else if (find_enclosing_rect(rects.$Silesia, x, y)) { + map = BOHEMIA + country = SILESIA + } + else if (find_enclosing_rect(rects.$Poland, x, y)) { + map = BOHEMIA + country = POLAND + } + else if (find_enclosing_rect(rects.$Prussia, x, y)) { + map = BOHEMIA + country = PRUSSIA + } + else if (find_enclosing_rect(rects.$Netherlands, x, y)) { + map = FLANDERS + country = NETHERLANDS + } + else if (find_enclosing_rect(rects.$France, x, y)) { + map = FLANDERS + country = FRANCE + } + + if (country === "UNKNOWN") + console.log("no country:", node) + + cities.push({ + name: node.name, + map, + country, + suit, + type: key, + x: Math.round(x), + y: Math.round(y), + major_roads: [], + roads: [], + }) } else { let [ dupname, dupdist ] = find_closest_node(all_labels, x, y) - console.log("ALREADY USED", dupname, dupdist, x, y, "OLD", out[dupname]) + console.log("ALREADY USED", dupname, dupdist, x, y) } } } +cities.sort((a,b) => { + if (a.map < b.map) return 1 + if (a.map > b.map) return -1 + if (a.country < b.country) return -1 + if (a.country > b.country) return 1 + if (a.suit < b.suit) return -1 + if (a.suit > b.suit) return 1 + if (a.type === "major_fortress" && b.type !== "major_fortress") return -1 + if (a.type !== "major_fortress" && b.type === "major_fortress") return 1 + if (a.type === "minor_fortress" && b.type !== "minor_fortress") return -1 + if (a.type !== "minor_fortress" && b.type === "minor_fortress") return 1 + if (a.name < b.name) return -1 + if (a.name > b.name) return 1 + return b.y - a.y +}) + +for (let e of edges.major_road) { + let a = find_closest_city(e.x1, e.y1) + let b = find_closest_city(e.x2, e.y2) + cities[a].major_roads.push(b) + cities[b].major_roads.push(a) +} + +for (let e of edges.road) { + let a = find_closest_city(e.x1, e.y1) + let b = find_closest_city(e.x2, e.y2) + cities[a].roads.push(b) + cities[b].roads.push(a) +} + +let arrays = { + name: [], + // map: [], + // country: [], + // suit: [], + // type: [], + x: [], + y: [], + major_roads: [], + roads: [], +} + +let sets = { + type: { + major_fortress: [], + minor_fortress: [], + city: [], + }, + suit: { + clubs: [], + diamonds: [], + hearts: [], + spades: [], + }, + map: { + Flanders: [], + Bohemia: [], + }, + country: { + Austria: [], + Bavaria: [], + France: [], + Netherlands: [], + Poland: [], + Prussia: [], + Saxony: [], + Silesia: [], + "Holy Roman Empire": [], + }, +} + +for (let i = 0; i < cities.length; ++i) { + let city = cities[i] + for (let key in city) { + if (arrays[key]) + arrays[key].push(city[key]) + if (sets[key]) + sets[key][city[key]].push(i) + } +} + +function map_to_range(x) { + let pairs = [] + let a = 0, b = 1 + for (; b < x.length; ++b) { + if (x[b-1] + 1 === x[b]) + continue + pairs.push([x[a],x[b-1]]) + a = b + } + pairs.push([x[a],x[b-1]]) + return pairs +} + +function remap_to_range(obj) { + for (let key in obj) + obj[key] = map_to_range(obj[key]) +} + +remap_to_range(sets.map) +remap_to_range(sets.suit) +remap_to_range(sets.country) + +delete sets.type.city + +sets.cities = arrays + +console.log("const data = " + JSON.stringify(sets)) +console.log("if (typeof module === 'object') module.exports = data") -- cgit v1.2.3